2021-05-22 20:47:08 +00:00
|
|
|
use super::{
|
|
|
|
animate_by_pulse, get_quality_col,
|
|
|
|
img_ids::{Imgs, ImgsRot},
|
|
|
|
item_imgs::ItemImgs,
|
Add ItemDesc::l10n method
- Add ItemL10n struct that is similar to ItemImgs except it holds i18n
description and not items. ItemDesc::l10n uses this struct to provide
common_i18n::Content for both names and descriptions.
So far it only used in voxygen, but it can be used by rtsim in
dialogues.
- Introduced new deprecation, ItemKind::Ingredient, because it uses
item.name().
It's not deleted, because it's used in inventory sorting, and our
inventory sorting is, for some reason, server-side.
- Crafting UI also still uses deprecated item.name(), because again,
sorting. It's probably will be easier to handle, because it's UI
sorting and we can use localized names here, but still, it's a thing
to discuss.
- Moved Item::describe() to voxygen/hud/util.
The most important thing to note is we don't want to completely delete
deprecated .name() and .description() along with corresponding fields
in ItemDef because ItemDef is now "public" API, exposed in plugins and I
don't want to break plugins before we actually implement i18n for them.
Otherwise, it would be basically impossible to use items in plugins.
What's left is actually fully implementing ItemDesc::l10n, create
item_l10n.ron and add fallback on current .name() and .description()
implementation.
2024-01-11 16:28:25 +00:00
|
|
|
util, HudInfo, Show, Windows, TEXT_COLOR,
|
2021-05-22 20:47:08 +00:00
|
|
|
};
|
2021-07-29 18:47:45 +00:00
|
|
|
use crate::ui::{fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable};
|
2021-05-22 20:47:08 +00:00
|
|
|
use client::Client;
|
2024-02-06 11:33:38 +00:00
|
|
|
use common::{
|
|
|
|
comp::inventory::item::{Item, ItemDesc, ItemI18n, MaterialStatManifest, Quality},
|
|
|
|
uid::Uid,
|
|
|
|
};
|
2024-02-10 10:34:14 +00:00
|
|
|
use common_net::sync::WorldSyncExt;
|
2021-05-22 20:47:08 +00:00
|
|
|
use conrod_core::{
|
|
|
|
color,
|
|
|
|
position::Dimension,
|
|
|
|
widget::{self, Image, List, Rectangle, Scrollbar, Text},
|
|
|
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
|
|
|
};
|
2021-07-29 18:47:45 +00:00
|
|
|
use i18n::Localization;
|
2022-05-09 03:30:56 +00:00
|
|
|
use std::collections::VecDeque;
|
2021-05-22 20:47:08 +00:00
|
|
|
|
|
|
|
widget_ids! {
|
|
|
|
struct Ids{
|
|
|
|
frame,
|
|
|
|
message_box,
|
|
|
|
scrollbar,
|
|
|
|
message_icons[],
|
|
|
|
message_icon_bgs[],
|
|
|
|
message_icon_frames[],
|
|
|
|
message_texts[],
|
|
|
|
message_text_shadows[],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const MAX_MESSAGES: usize = 50;
|
|
|
|
|
|
|
|
const BOX_WIDTH: f64 = 300.0;
|
|
|
|
const BOX_HEIGHT: f64 = 350.0;
|
|
|
|
|
|
|
|
const ICON_BG_SIZE: f64 = 33.0;
|
|
|
|
const ICON_SIZE: f64 = 30.0;
|
|
|
|
const ICON_LABEL_SPACER: f64 = 7.0;
|
|
|
|
|
|
|
|
const MESSAGE_VERTICAL_PADDING: f64 = 1.0;
|
|
|
|
|
|
|
|
const HOVER_FADE_OUT_TIME: f32 = 2.0;
|
|
|
|
const MESSAGE_FADE_OUT_TIME: f32 = 4.5;
|
|
|
|
const AUTO_SHOW_FADE_OUT_TIME: f32 = 1.0;
|
|
|
|
|
|
|
|
const MAX_MERGE_TIME: f32 = MESSAGE_FADE_OUT_TIME;
|
|
|
|
|
|
|
|
#[derive(WidgetCommon)]
|
|
|
|
pub struct LootScroller<'a> {
|
|
|
|
new_messages: &'a mut VecDeque<LootMessage>,
|
|
|
|
|
|
|
|
client: &'a Client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info: &'a HudInfo,
|
2021-05-22 20:47:08 +00:00
|
|
|
show: &'a Show,
|
|
|
|
imgs: &'a Imgs,
|
|
|
|
item_imgs: &'a ItemImgs,
|
|
|
|
rot_imgs: &'a ImgsRot,
|
|
|
|
fonts: &'a Fonts,
|
|
|
|
localized_strings: &'a Localization,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n: &'a ItemI18n,
|
2021-05-22 20:47:08 +00:00
|
|
|
msm: &'a MaterialStatManifest,
|
|
|
|
item_tooltip_manager: &'a mut ItemTooltipManager,
|
|
|
|
pulse: f32,
|
|
|
|
|
|
|
|
#[conrod(common_builder)]
|
|
|
|
common: widget::CommonBuilder,
|
|
|
|
}
|
|
|
|
impl<'a> LootScroller<'a> {
|
|
|
|
pub fn new(
|
|
|
|
new_messages: &'a mut VecDeque<LootMessage>,
|
|
|
|
client: &'a Client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info: &'a HudInfo,
|
2021-05-22 20:47:08 +00:00
|
|
|
show: &'a Show,
|
|
|
|
imgs: &'a Imgs,
|
|
|
|
item_imgs: &'a ItemImgs,
|
|
|
|
rot_imgs: &'a ImgsRot,
|
|
|
|
fonts: &'a Fonts,
|
|
|
|
localized_strings: &'a Localization,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n: &'a ItemI18n,
|
2021-05-22 20:47:08 +00:00
|
|
|
msm: &'a MaterialStatManifest,
|
|
|
|
item_tooltip_manager: &'a mut ItemTooltipManager,
|
|
|
|
pulse: f32,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
new_messages,
|
|
|
|
client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info,
|
2021-05-22 20:47:08 +00:00
|
|
|
show,
|
|
|
|
imgs,
|
|
|
|
item_imgs,
|
|
|
|
rot_imgs,
|
|
|
|
fonts,
|
|
|
|
localized_strings,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n,
|
2021-05-22 20:47:08 +00:00
|
|
|
msm,
|
|
|
|
item_tooltip_manager,
|
|
|
|
pulse,
|
|
|
|
common: widget::CommonBuilder::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
pub struct LootMessage {
|
2022-05-09 03:30:56 +00:00
|
|
|
pub item: Item,
|
2021-05-22 20:47:08 +00:00
|
|
|
pub amount: u32,
|
2024-02-06 11:33:38 +00:00
|
|
|
pub taken_by: Uid,
|
2021-05-22 20:47:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct State {
|
|
|
|
ids: Ids,
|
|
|
|
messages: VecDeque<(LootMessage, f32)>, // (message, timestamp)
|
|
|
|
|
|
|
|
last_hover_pulse: Option<f32>,
|
|
|
|
last_auto_show_pulse: Option<f32>, // auto show if (for example) bag is open
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Widget for LootScroller<'a> {
|
|
|
|
type Event = ();
|
|
|
|
type State = State;
|
|
|
|
type Style = ();
|
|
|
|
|
|
|
|
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
|
|
|
State {
|
|
|
|
ids: Ids::new(id_gen),
|
|
|
|
messages: VecDeque::new(),
|
|
|
|
last_hover_pulse: None,
|
|
|
|
last_auto_show_pulse: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-14 19:42:29 +00:00
|
|
|
fn style(&self) -> Self::Style {}
|
2021-05-22 20:47:08 +00:00
|
|
|
|
|
|
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
|
|
|
let widget::UpdateArgs { state, ui, .. } = args;
|
|
|
|
|
|
|
|
// Tooltips
|
|
|
|
let item_tooltip = ItemTooltip::new(
|
|
|
|
{
|
|
|
|
// Edge images [t, b, r, l]
|
|
|
|
// Corner images [tr, tl, br, bl]
|
|
|
|
let edge = &self.rot_imgs.tt_side;
|
|
|
|
let corner = &self.rot_imgs.tt_corner;
|
|
|
|
ImageFrame::new(
|
|
|
|
[edge.cw180, edge.none, edge.cw270, edge.cw90],
|
|
|
|
[corner.none, corner.cw270, corner.cw90, corner.cw180],
|
|
|
|
Color::Rgba(0.08, 0.07, 0.04, 1.0),
|
|
|
|
5.0,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
self.client,
|
2022-07-06 09:20:18 +00:00
|
|
|
self.info,
|
2021-05-22 20:47:08 +00:00
|
|
|
self.imgs,
|
|
|
|
self.item_imgs,
|
|
|
|
self.pulse,
|
|
|
|
self.msm,
|
|
|
|
self.localized_strings,
|
2024-01-16 16:40:12 +00:00
|
|
|
self.item_i18n,
|
2021-05-22 20:47:08 +00:00
|
|
|
)
|
|
|
|
.title_font_size(self.fonts.cyri.scale(20))
|
|
|
|
.parent(ui.window)
|
|
|
|
.desc_font_size(self.fonts.cyri.scale(12))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.desc_text_color(TEXT_COLOR);
|
|
|
|
|
|
|
|
if !self.new_messages.is_empty() {
|
|
|
|
let pulse = self.pulse;
|
|
|
|
let oldest_merge_pulse = pulse - MAX_MERGE_TIME;
|
|
|
|
|
|
|
|
state.update(|s| {
|
|
|
|
s.messages.retain(|(message, t)| {
|
|
|
|
if *t >= oldest_merge_pulse {
|
2022-05-09 03:30:56 +00:00
|
|
|
if let Some(i) = self.new_messages.iter().position(|m| {
|
|
|
|
m.item.item_definition_id() == message.item.item_definition_id()
|
2023-04-06 18:43:11 +00:00
|
|
|
&& m.taken_by == message.taken_by
|
2022-05-09 03:30:56 +00:00
|
|
|
}) {
|
2021-05-22 20:47:08 +00:00
|
|
|
self.new_messages[i].amount += message.amount;
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
s.messages
|
|
|
|
.extend(self.new_messages.drain(..).map(|message| (message, pulse)));
|
|
|
|
while s.messages.len() > MAX_MESSAGES {
|
|
|
|
s.messages.pop_front();
|
|
|
|
}
|
|
|
|
});
|
2021-07-11 11:13:36 +00:00
|
|
|
ui.scroll_widget(state.ids.message_box, [0.0, f64::MAX]);
|
2021-05-22 20:47:08 +00:00
|
|
|
}
|
|
|
|
|
2021-05-31 19:29:35 +00:00
|
|
|
// check if it collides with other windows
|
|
|
|
if self.show.diary
|
|
|
|
|| self.show.map
|
|
|
|
|| self.show.open_windows != Windows::None
|
|
|
|
|| self.show.social
|
|
|
|
|| self.show.trade
|
|
|
|
{
|
2021-05-22 20:47:08 +00:00
|
|
|
if state.last_hover_pulse.is_some() || state.last_auto_show_pulse.is_some() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.last_hover_pulse = None;
|
|
|
|
s.last_auto_show_pulse = None;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
2021-05-31 19:29:35 +00:00
|
|
|
//check if hovered
|
2021-05-22 20:47:08 +00:00
|
|
|
if ui
|
|
|
|
.rect_of(state.ids.message_box)
|
2021-05-31 19:29:35 +00:00
|
|
|
.map(|r| r.pad_left(-6.0))
|
2021-05-22 20:47:08 +00:00
|
|
|
.map_or(false, |r| r.is_over(ui.global_input().current.mouse.xy))
|
|
|
|
{
|
|
|
|
state.update(|s| s.last_hover_pulse = Some(self.pulse));
|
|
|
|
}
|
|
|
|
|
|
|
|
if state.ids.message_icons.len() < state.messages.len() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.message_icons
|
|
|
|
.resize(s.messages.len(), &mut ui.widget_id_generator())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if state.ids.message_icon_bgs.len() < state.messages.len() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.message_icon_bgs
|
|
|
|
.resize(s.messages.len(), &mut ui.widget_id_generator())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if state.ids.message_icon_frames.len() < state.messages.len() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.message_icon_frames
|
|
|
|
.resize(s.messages.len(), &mut ui.widget_id_generator())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if state.ids.message_texts.len() < state.messages.len() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.message_texts
|
|
|
|
.resize(s.messages.len(), &mut ui.widget_id_generator())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if state.ids.message_text_shadows.len() < state.messages.len() {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.message_text_shadows
|
|
|
|
.resize(s.messages.len(), &mut ui.widget_id_generator())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
let hover_age = state
|
|
|
|
.last_hover_pulse
|
|
|
|
.map_or(1.0, |t| (self.pulse - t) / HOVER_FADE_OUT_TIME);
|
|
|
|
let auto_show_age = state
|
|
|
|
.last_auto_show_pulse
|
|
|
|
.map_or(1.0, |t| (self.pulse - t) / AUTO_SHOW_FADE_OUT_TIME);
|
|
|
|
|
|
|
|
let show_all_age = hover_age.min(auto_show_age);
|
|
|
|
|
|
|
|
let messages_to_display = state
|
|
|
|
.messages
|
|
|
|
.iter()
|
|
|
|
.rev()
|
|
|
|
.map(|(message, t)| {
|
|
|
|
let age = (self.pulse - t) / MESSAGE_FADE_OUT_TIME;
|
|
|
|
(message, age)
|
|
|
|
})
|
|
|
|
.filter(|(_, age)| age.min(show_all_age) < 1.0)
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
let (mut list_messages, _) = List::flow_up(messages_to_display.len())
|
|
|
|
.w_h(BOX_WIDTH, BOX_HEIGHT)
|
|
|
|
.scroll_kids_vertically()
|
|
|
|
.bottom_left_with_margins_on(ui.window, 308.0, 20.0)
|
|
|
|
.set(state.ids.message_box, ui);
|
|
|
|
|
2021-05-31 19:29:35 +00:00
|
|
|
//only show scrollbar if it is being hovered and needed
|
2021-05-22 20:47:08 +00:00
|
|
|
if show_all_age < 1.0
|
|
|
|
&& ui
|
|
|
|
.widget_graph()
|
|
|
|
.widget(state.ids.message_box)
|
2021-12-21 20:19:23 +00:00
|
|
|
.and_then(|w| w.maybe_y_scroll_state)
|
2021-05-22 20:47:08 +00:00
|
|
|
.map_or(false, |s| s.scrollable_range_len > BOX_HEIGHT)
|
|
|
|
{
|
|
|
|
Scrollbar::y_axis(state.ids.message_box)
|
|
|
|
.thickness(5.0)
|
|
|
|
.rgba(0.33, 0.33, 0.33, 1.0 - show_all_age.powi(4))
|
|
|
|
.left_from(state.ids.message_box, 1.0)
|
|
|
|
.set(state.ids.scrollbar, ui);
|
|
|
|
}
|
|
|
|
|
2024-02-12 20:13:18 +00:00
|
|
|
let stats = self.client.state().read_storage::<common::comp::Stats>();
|
|
|
|
|
2021-05-22 20:47:08 +00:00
|
|
|
while let Some(list_message) = list_messages.next(ui) {
|
|
|
|
let i = list_message.i;
|
|
|
|
|
|
|
|
let (message, age) = messages_to_display[i];
|
2022-09-20 22:13:50 +00:00
|
|
|
let LootMessage {
|
|
|
|
item,
|
|
|
|
amount,
|
|
|
|
taken_by,
|
|
|
|
} = message;
|
2021-05-22 20:47:08 +00:00
|
|
|
|
|
|
|
let alpha = 1.0 - age.min(show_all_age).powi(4);
|
|
|
|
|
|
|
|
let brightness = 1.0 / (age / 0.05 - 1.0).abs().clamp(0.01, 1.0);
|
|
|
|
|
|
|
|
let shade_color = |color: Color| {
|
|
|
|
let color::Hsla(hue, sat, lum, alp) = color.to_hsl();
|
|
|
|
color::hsla(hue, sat / brightness, lum * brightness.sqrt(), alp * alpha)
|
|
|
|
};
|
|
|
|
|
2021-08-01 03:53:52 +00:00
|
|
|
let quality_col_image = match item.quality() {
|
2021-05-22 20:47:08 +00:00
|
|
|
Quality::Low => self.imgs.inv_slot_grey,
|
2021-11-04 17:50:14 +00:00
|
|
|
Quality::Common => self.imgs.inv_slot_common,
|
2021-05-22 20:47:08 +00:00
|
|
|
Quality::Moderate => self.imgs.inv_slot_green,
|
|
|
|
Quality::High => self.imgs.inv_slot_blue,
|
|
|
|
Quality::Epic => self.imgs.inv_slot_purple,
|
|
|
|
Quality::Legendary => self.imgs.inv_slot_gold,
|
|
|
|
Quality::Artifact => self.imgs.inv_slot_orange,
|
|
|
|
_ => self.imgs.inv_slot_red,
|
|
|
|
};
|
2024-02-06 11:33:38 +00:00
|
|
|
let quality_col = get_quality_col(&item);
|
2021-05-22 20:47:08 +00:00
|
|
|
|
|
|
|
Image::new(self.imgs.pixel)
|
|
|
|
.color(Some(shade_color(quality_col.alpha(0.7))))
|
|
|
|
.w_h(ICON_BG_SIZE, ICON_BG_SIZE)
|
|
|
|
.top_left_with_margins_on(list_message.widget_id, MESSAGE_VERTICAL_PADDING, 0.0)
|
|
|
|
.set(state.ids.message_icon_bgs[i], ui);
|
|
|
|
|
|
|
|
Image::new(quality_col_image)
|
|
|
|
.color(Some(shade_color(color::hsla(0.0, 0.0, 1.0, 1.0))))
|
|
|
|
.wh_of(state.ids.message_icon_bgs[i])
|
|
|
|
.middle_of(state.ids.message_icon_bgs[i])
|
|
|
|
.set(state.ids.message_icon_frames[i], ui);
|
|
|
|
|
|
|
|
Image::new(animate_by_pulse(
|
2022-09-08 19:51:02 +00:00
|
|
|
&self.item_imgs.img_ids_or_not_found_img(item.into()),
|
2021-05-22 20:47:08 +00:00
|
|
|
self.pulse,
|
|
|
|
))
|
|
|
|
.color(Some(shade_color(color::hsla(0.0, 0.0, 1.0, 1.0))))
|
|
|
|
.w_h(ICON_SIZE, ICON_SIZE)
|
|
|
|
.middle_of(state.ids.message_icon_bgs[i])
|
2021-10-14 00:00:45 +00:00
|
|
|
.with_item_tooltip(
|
|
|
|
self.item_tooltip_manager,
|
2022-09-08 19:51:02 +00:00
|
|
|
core::iter::once(item as &dyn ItemDesc),
|
2021-10-14 00:00:45 +00:00
|
|
|
&None,
|
|
|
|
&item_tooltip,
|
|
|
|
)
|
2021-05-22 20:47:08 +00:00
|
|
|
.set(state.ids.message_icons[i], ui);
|
2024-02-10 10:34:14 +00:00
|
|
|
|
2024-02-12 17:01:39 +00:00
|
|
|
let target_name = self
|
|
|
|
.client
|
|
|
|
.player_list()
|
|
|
|
.get(taken_by)
|
|
|
|
.map_or_else(
|
|
|
|
|| {
|
|
|
|
self.client
|
|
|
|
.state()
|
|
|
|
.ecs()
|
|
|
|
.entity_from_uid(*taken_by)
|
2024-02-12 20:13:18 +00:00
|
|
|
.and_then(|entity| stats.get(entity).map(|e| e.name.clone()))
|
2024-02-10 10:34:14 +00:00
|
|
|
},
|
2024-02-12 17:01:39 +00:00
|
|
|
|info| Some(info.player_alias.clone()),
|
|
|
|
)
|
|
|
|
.unwrap_or_else(|| format!("<uid {}>", *taken_by));
|
2024-02-10 10:34:14 +00:00
|
|
|
|
|
|
|
let (user_gender, is_you) = match self.client.player_list().get(taken_by) {
|
2024-02-06 11:33:38 +00:00
|
|
|
Some(player_info) => match player_info.character.as_ref() {
|
2024-02-10 10:34:14 +00:00
|
|
|
Some(character_info) => (
|
|
|
|
match character_info.gender {
|
|
|
|
Some(common::comp::Gender::Feminine) => "she".to_string(),
|
|
|
|
Some(common::comp::Gender::Masculine) => "he".to_string(),
|
|
|
|
None => "??".to_string(),
|
|
|
|
},
|
|
|
|
self.client.uid().expect("Client doesn't have a Uid!!!") == *taken_by,
|
|
|
|
),
|
|
|
|
None => ("??".to_string(), false),
|
|
|
|
},
|
|
|
|
None => ("??".to_string(), false),
|
2024-02-06 11:33:38 +00:00
|
|
|
};
|
|
|
|
|
2024-02-12 20:13:18 +00:00
|
|
|
let label = if is_you {
|
|
|
|
self.localized_strings.get_msg_ctx(
|
2024-02-12 17:01:39 +00:00
|
|
|
"hud-loot-pickup-msg-you",
|
|
|
|
&i18n::fluent_args! {
|
|
|
|
"gender" => user_gender,
|
|
|
|
"amount" => amount,
|
|
|
|
"item" => {
|
|
|
|
let (name, _) =
|
|
|
|
util::item_text(&item, self.localized_strings, self.item_i18n);
|
|
|
|
name
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
2024-02-12 20:13:18 +00:00
|
|
|
} else {
|
|
|
|
self.localized_strings.get_msg_ctx(
|
2024-02-12 17:01:39 +00:00
|
|
|
"hud-loot-pickup-msg",
|
|
|
|
&i18n::fluent_args! {
|
|
|
|
"gender" => user_gender,
|
|
|
|
"actor" => target_name,
|
|
|
|
"amount" => amount,
|
|
|
|
"item" => {
|
|
|
|
let (name, _) =
|
|
|
|
util::item_text(&item, self.localized_strings, self.item_i18n);
|
|
|
|
name
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-05-22 20:47:08 +00:00
|
|
|
let label_font_size = 20;
|
|
|
|
|
|
|
|
Text::new(&label)
|
|
|
|
.top_left_with_margins_on(
|
|
|
|
list_message.widget_id,
|
|
|
|
MESSAGE_VERTICAL_PADDING + 1.0,
|
|
|
|
ICON_BG_SIZE + ICON_LABEL_SPACER,
|
|
|
|
)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(label_font_size))
|
|
|
|
.color(shade_color(quality_col))
|
|
|
|
.graphics_for(state.ids.message_icons[i])
|
|
|
|
.and(|text| {
|
|
|
|
let text_width = match text.get_x_dimension(ui) {
|
|
|
|
Dimension::Absolute(x) => x,
|
2021-07-11 11:13:36 +00:00
|
|
|
_ => f64::MAX,
|
2021-05-22 20:47:08 +00:00
|
|
|
}
|
|
|
|
.min(BOX_WIDTH - (ICON_BG_SIZE + ICON_LABEL_SPACER));
|
|
|
|
text.w(text_width)
|
|
|
|
})
|
|
|
|
.set(state.ids.message_texts[i], ui);
|
|
|
|
Text::new(&label)
|
|
|
|
.depth(1.0)
|
|
|
|
.parent(list_message.widget_id)
|
|
|
|
.x_y_relative_to(state.ids.message_texts[i], -1.0, -1.0)
|
|
|
|
.wh_of(state.ids.message_texts[i])
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(label_font_size))
|
|
|
|
.color(shade_color(color::rgba(0.0, 0.0, 0.0, 1.0)))
|
|
|
|
.set(state.ids.message_text_shadows[i], ui);
|
|
|
|
|
|
|
|
let height = 2.0 * MESSAGE_VERTICAL_PADDING
|
|
|
|
+ ICON_BG_SIZE.max(
|
|
|
|
1.0 + ui
|
|
|
|
.rect_of(state.ids.message_texts[i])
|
|
|
|
.map_or(0.0, |r| r.h() + label_font_size as f64 / 3.0),
|
|
|
|
/* add to height since rect height does not account for lower parts of
|
|
|
|
* letters */
|
|
|
|
);
|
|
|
|
|
|
|
|
let rect = Rectangle::fill_with([BOX_WIDTH, height], color::TRANSPARENT);
|
|
|
|
|
|
|
|
list_message.set(rect, ui);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|