mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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.
This commit is contained in:
parent
8263154a7e
commit
18e507315f
@ -14,7 +14,7 @@ pub enum ItemKey {
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl<T: ItemDesc> From<&T> for ItemKey {
|
||||
impl<T: ItemDesc + ?Sized> From<&T> for ItemKey {
|
||||
fn from(item_desc: &T) -> Self {
|
||||
let item_definition_id = item_desc.item_definition_id();
|
||||
|
||||
|
@ -14,13 +14,15 @@ use crate::{
|
||||
recipe::RecipeInput,
|
||||
terrain::Block,
|
||||
};
|
||||
use common_i18n::Content;
|
||||
use core::{
|
||||
convert::TryFrom,
|
||||
mem,
|
||||
num::{NonZeroU32, NonZeroU64},
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use hashbrown::Equivalent;
|
||||
use hashbrown::{Equivalent, HashMap};
|
||||
use item_key::ItemKey;
|
||||
use serde::{de, Deserialize, Serialize, Serializer};
|
||||
use specs::{Component, DenseVecStorage, DerefFlaggedStorage};
|
||||
use std::{borrow::Cow, collections::hash_map::DefaultHasher, fmt, sync::Arc};
|
||||
@ -342,6 +344,7 @@ pub enum ItemKind {
|
||||
},
|
||||
Ingredient {
|
||||
/// Used to generate names for modular items composed of this ingredient
|
||||
#[deprecated]
|
||||
descriptor: String,
|
||||
},
|
||||
TagExamples {
|
||||
@ -383,6 +386,7 @@ impl ItemKind {
|
||||
},
|
||||
ItemKind::Throwable { kind } => format!("Throwable: {:?}", kind),
|
||||
ItemKind::Utility { kind } => format!("Utility: {:?}", kind),
|
||||
#[allow(deprecated)]
|
||||
ItemKind::Ingredient { descriptor } => format!("Ingredient: {}", descriptor),
|
||||
ItemKind::TagExamples { item_ids } => format!("TagExamples: {:?}", item_ids),
|
||||
}
|
||||
@ -466,11 +470,28 @@ impl Hash for Item {
|
||||
}
|
||||
}
|
||||
|
||||
// at the time of writing, we use Fluent, which supports attributes
|
||||
// and we can get both name and description using them
|
||||
type I18nId = String;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ItemName {
|
||||
Direct(String),
|
||||
Modular,
|
||||
Component(String),
|
||||
// TODO: probably make a Resource if used outside of voxygen
|
||||
// TODO: add hot-reloading similar to how ItemImgs does it?
|
||||
// TODO: make it work with plugins (via Concatenate?)
|
||||
/// To be used with ItemDesc::l10n
|
||||
pub struct ItemL10n {
|
||||
/// maps ItemKey to i18n identifier
|
||||
map: HashMap<ItemKey, I18nId>,
|
||||
}
|
||||
|
||||
impl assets::Asset for ItemL10n {
|
||||
type Loader = assets::RonLoader;
|
||||
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
impl ItemL10n {
|
||||
pub fn new_expect() -> Self { ItemL10n::load_expect("common.item_l10n").read().clone() }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -1147,16 +1168,6 @@ impl Item {
|
||||
})
|
||||
}
|
||||
|
||||
/// Generate a human-readable description of the item and amount.
|
||||
#[deprecated]
|
||||
pub fn describe(&self) -> String {
|
||||
if self.amount() > 1 {
|
||||
format!("{} x {}", self.amount(), self.name())
|
||||
} else {
|
||||
self.name().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn name(&self) -> Cow<str> {
|
||||
match &self.item_base {
|
||||
@ -1400,6 +1411,7 @@ pub fn flatten_counted_items<'a>(
|
||||
pub trait ItemDesc {
|
||||
#[deprecated]
|
||||
fn description(&self) -> &str;
|
||||
#[deprecated]
|
||||
fn name(&self) -> Cow<str>;
|
||||
fn kind(&self) -> Cow<ItemKind>;
|
||||
fn amount(&self) -> NonZeroU32;
|
||||
@ -1420,6 +1432,18 @@ pub trait ItemDesc {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Return name's and description's localization descriptors
|
||||
fn l10n(&self, l10n: &ItemL10n) -> (Content, Content) {
|
||||
let item_key: ItemKey = self.into();
|
||||
|
||||
let _key = l10n.map.get(&item_key);
|
||||
(
|
||||
// construct smth like Content::Attr
|
||||
todo!(),
|
||||
todo!(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemDesc for Item {
|
||||
|
@ -3,7 +3,7 @@ use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::ItemImgs,
|
||||
slots::{ArmorSlot, EquipSlot, InventorySlot, SlotManager},
|
||||
HudInfo, Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
util, HudInfo, Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
};
|
||||
use crate::{
|
||||
game_input::GameInput,
|
||||
@ -21,7 +21,7 @@ use common::{
|
||||
combat::{combat_rating, perception_dist_multiplier_from_stealth, Damage},
|
||||
comp::{
|
||||
inventory::InventorySortOrder,
|
||||
item::{ItemDef, ItemDesc, MaterialStatManifest, Quality},
|
||||
item::{ItemDef, ItemDesc, ItemL10n, MaterialStatManifest, Quality},
|
||||
Body, Energy, Health, Inventory, Poise, SkillSet, Stats,
|
||||
},
|
||||
};
|
||||
@ -81,6 +81,7 @@ pub struct InventoryScroller<'a> {
|
||||
slot_manager: &'a mut SlotManager,
|
||||
pulse: f32,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
show_stats: bool,
|
||||
show_bag_inv: bool,
|
||||
on_right: bool,
|
||||
@ -105,6 +106,7 @@ impl<'a> InventoryScroller<'a> {
|
||||
slot_manager: &'a mut SlotManager,
|
||||
pulse: f32,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
show_stats: bool,
|
||||
show_bag_inv: bool,
|
||||
on_right: bool,
|
||||
@ -127,6 +129,7 @@ impl<'a> InventoryScroller<'a> {
|
||||
slot_manager,
|
||||
pulse,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
show_stats,
|
||||
show_bag_inv,
|
||||
on_right,
|
||||
@ -365,8 +368,18 @@ impl<'a> InventoryScroller<'a> {
|
||||
items.sort_by_cached_key(|(_, item)| {
|
||||
(
|
||||
item.is_none(),
|
||||
item.as_ref()
|
||||
.map(|i| (std::cmp::Reverse(i.quality()), i.name(), i.amount())),
|
||||
item.as_ref().map(|i| {
|
||||
(
|
||||
std::cmp::Reverse(i.quality()),
|
||||
{
|
||||
// TODO: we do double the work here, optimize?
|
||||
let (name, _) =
|
||||
util::item_text(i, self.localized_strings, self.item_l10n);
|
||||
name
|
||||
},
|
||||
i.amount(),
|
||||
)
|
||||
}),
|
||||
)
|
||||
});
|
||||
}
|
||||
@ -457,7 +470,8 @@ impl<'a> InventoryScroller<'a> {
|
||||
.set(state.ids.inv_slots[i], ui);
|
||||
}
|
||||
if self.details_mode {
|
||||
Text::new(&item.name())
|
||||
let (name, _) = util::item_text(item, self.localized_strings, self.item_l10n);
|
||||
Text::new(&name)
|
||||
.top_left_with_margins_on(
|
||||
state.ids.inv_alignment,
|
||||
0.0 + y as f64 * slot_size,
|
||||
@ -638,6 +652,7 @@ pub struct Bag<'a> {
|
||||
slot_manager: &'a mut SlotManager,
|
||||
pulse: f32,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
stats: &'a Stats,
|
||||
skill_set: &'a SkillSet,
|
||||
health: &'a Health,
|
||||
@ -663,6 +678,7 @@ impl<'a> Bag<'a> {
|
||||
slot_manager: &'a mut SlotManager,
|
||||
pulse: f32,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
stats: &'a Stats,
|
||||
skill_set: &'a SkillSet,
|
||||
health: &'a Health,
|
||||
@ -686,6 +702,7 @@ impl<'a> Bag<'a> {
|
||||
slot_manager,
|
||||
pulse,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
stats,
|
||||
skill_set,
|
||||
energy,
|
||||
@ -805,6 +822,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
self.pulse,
|
||||
self.msm,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
)
|
||||
.title_font_size(self.fonts.cyri.scale(20))
|
||||
.parent(ui.window)
|
||||
@ -821,6 +839,7 @@ impl<'a> Widget for Bag<'a> {
|
||||
self.slot_manager,
|
||||
self.pulse,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
self.show.stats,
|
||||
self.show.bag_inv,
|
||||
true,
|
||||
|
@ -3,7 +3,7 @@ use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::{animate_by_pulse, ItemImgs},
|
||||
slots::{CraftSlot, CraftSlotInfo, SlotManager},
|
||||
HudInfo, Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
util, HudInfo, Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
};
|
||||
use crate::ui::{
|
||||
fonts::Fonts,
|
||||
@ -19,8 +19,8 @@ use common::{
|
||||
item_key::ItemKey,
|
||||
modular::{self, ModularComponent},
|
||||
tool::{AbilityMap, ToolKind},
|
||||
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, MaterialStatManifest, Quality,
|
||||
TagExampleInfo,
|
||||
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemL10n, ItemTag, MaterialStatManifest,
|
||||
Quality, TagExampleInfo,
|
||||
},
|
||||
slot::{InvSlotId, Slot},
|
||||
Inventory,
|
||||
@ -151,6 +151,7 @@ pub struct Crafting<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
pulse: f32,
|
||||
rot_imgs: &'a ImgsRot,
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
@ -171,6 +172,7 @@ impl<'a> Crafting<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
pulse: f32,
|
||||
rot_imgs: &'a ImgsRot,
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
@ -187,6 +189,7 @@ impl<'a> Crafting<'a> {
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
pulse,
|
||||
rot_imgs,
|
||||
item_tooltip_manager,
|
||||
@ -355,6 +358,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
self.pulse,
|
||||
self.msm,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
)
|
||||
.title_font_size(self.fonts.cyri.scale(20))
|
||||
.parent(ui.window)
|
||||
@ -594,6 +598,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.iter()
|
||||
.filter(|(_, recipe)| match search_filter {
|
||||
SearchFilter::None => {
|
||||
#[allow(deprecated)]
|
||||
let output_name = recipe.output.0.name().to_lowercase();
|
||||
search_keys
|
||||
.iter()
|
||||
@ -608,9 +613,11 @@ impl<'a> Widget for Crafting<'a> {
|
||||
};
|
||||
|
||||
match input {
|
||||
#[allow(deprecated)]
|
||||
RecipeInput::Item(def) => search(&def.name()),
|
||||
RecipeInput::Tag(tag) => search(tag.name()),
|
||||
RecipeInput::TagSameItem(tag) => search(tag.name()),
|
||||
#[allow(deprecated)]
|
||||
RecipeInput::ListSameItem(defs) => {
|
||||
defs.iter().any(|def| search(&def.name()))
|
||||
},
|
||||
@ -667,6 +674,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
!is_craftable,
|
||||
!has_materials,
|
||||
recipe.output.0.quality(),
|
||||
#[allow(deprecated)]
|
||||
recipe.output.0.name(),
|
||||
)
|
||||
});
|
||||
@ -1214,6 +1222,8 @@ impl<'a> Widget for Crafting<'a> {
|
||||
};
|
||||
|
||||
if let Some(output_item) = output_item {
|
||||
let (name, _) =
|
||||
util::item_text(&output_item, self.localized_strings, self.item_l10n);
|
||||
Button::image(animate_by_pulse(
|
||||
&self
|
||||
.item_imgs
|
||||
@ -1221,7 +1231,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
self.pulse,
|
||||
))
|
||||
.w_h(55.0, 55.0)
|
||||
.label(&output_item.name())
|
||||
.label(&name)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
@ -1926,6 +1936,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeCraftingTab(CraftingTab::All));
|
||||
#[allow(deprecated)]
|
||||
events.push(Event::SearchRecipe(Some(item_def.name().to_string())));
|
||||
}
|
||||
// Item image
|
||||
@ -1963,7 +1974,13 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.req_text[i], ui);
|
||||
Text::new(&item_def.name())
|
||||
|
||||
let (name, _) = util::item_text(
|
||||
item_def.as_ref(),
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
);
|
||||
Text::new(&name)
|
||||
.right_from(state.ids.ingredient_frame[i], 10.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
@ -1972,14 +1989,35 @@ impl<'a> Widget for Crafting<'a> {
|
||||
} else {
|
||||
// Ingredients
|
||||
let name = match recipe_input {
|
||||
RecipeInput::Item(_) => item_def.name().to_string(),
|
||||
RecipeInput::Item(_) => {
|
||||
let (name, _) = util::item_text(
|
||||
item_def.as_ref(),
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
);
|
||||
|
||||
name
|
||||
},
|
||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => {
|
||||
// TODO: Localize!
|
||||
format!("Any {} item", tag.name())
|
||||
},
|
||||
RecipeInput::ListSameItem(item_defs) => {
|
||||
// TODO: Localize!
|
||||
format!(
|
||||
"Any of {}",
|
||||
item_defs.iter().map(|def| def.name()).collect::<String>()
|
||||
item_defs
|
||||
.iter()
|
||||
.map(|def| {
|
||||
let (name, _) = util::item_text(
|
||||
def.as_ref(),
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
);
|
||||
|
||||
name
|
||||
})
|
||||
.collect::<String>()
|
||||
)
|
||||
},
|
||||
};
|
||||
|
@ -2,11 +2,11 @@ use super::{
|
||||
animate_by_pulse, get_quality_col,
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::ItemImgs,
|
||||
HudInfo, Show, Windows, TEXT_COLOR,
|
||||
util, HudInfo, Show, Windows, TEXT_COLOR,
|
||||
};
|
||||
use crate::ui::{fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable};
|
||||
use client::Client;
|
||||
use common::comp::inventory::item::{Item, ItemDesc, MaterialStatManifest, Quality};
|
||||
use common::comp::inventory::item::{Item, ItemDesc, ItemL10n, MaterialStatManifest, Quality};
|
||||
use conrod_core::{
|
||||
color,
|
||||
position::Dimension,
|
||||
@ -58,6 +58,7 @@ pub struct LootScroller<'a> {
|
||||
rot_imgs: &'a ImgsRot,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
msm: &'a MaterialStatManifest,
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
pulse: f32,
|
||||
@ -76,6 +77,7 @@ impl<'a> LootScroller<'a> {
|
||||
rot_imgs: &'a ImgsRot,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
msm: &'a MaterialStatManifest,
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
pulse: f32,
|
||||
@ -90,6 +92,7 @@ impl<'a> LootScroller<'a> {
|
||||
rot_imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
msm,
|
||||
item_tooltip_manager,
|
||||
pulse,
|
||||
@ -153,6 +156,7 @@ impl<'a> Widget for LootScroller<'a> {
|
||||
self.pulse,
|
||||
self.msm,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
)
|
||||
.title_font_size(self.fonts.cyri.scale(20))
|
||||
.parent(ui.window)
|
||||
@ -351,7 +355,11 @@ impl<'a> Widget for LootScroller<'a> {
|
||||
&i18n::fluent_args! {
|
||||
"actor" => taken_by,
|
||||
"amount" => amount,
|
||||
"item" => item.name(),
|
||||
"item" => {
|
||||
let (name, _) =
|
||||
util::item_text(&item, self.localized_strings, self.item_l10n);
|
||||
name
|
||||
},
|
||||
},
|
||||
);
|
||||
let label_font_size = 20;
|
||||
|
@ -98,7 +98,7 @@ use common::{
|
||||
},
|
||||
item::{
|
||||
tool::{AbilityContext, ToolKind},
|
||||
ItemDesc, MaterialStatManifest, Quality,
|
||||
ItemDefinitionIdOwned, ItemDesc, ItemL10n, MaterialStatManifest, Quality,
|
||||
},
|
||||
loot_owner::LootOwnerKind,
|
||||
pet::is_mountable,
|
||||
@ -1286,6 +1286,7 @@ pub struct Hud {
|
||||
world_map: (/* Id */ Vec<Rotations>, Vec2<u32>),
|
||||
imgs: Imgs,
|
||||
item_imgs: ItemImgs,
|
||||
item_l10n: ItemL10n,
|
||||
fonts: Fonts,
|
||||
rot_imgs: ImgsRot,
|
||||
failed_block_pickups: HashMap<VolumePos, CollectFailedData>,
|
||||
@ -1341,6 +1342,8 @@ impl Hud {
|
||||
let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load rot images!");
|
||||
// Load item images.
|
||||
let item_imgs = ItemImgs::new(&mut ui, imgs.not_found);
|
||||
// Load item text ("reference" to name and description)
|
||||
let item_l10n = ItemL10n::new_expect();
|
||||
// Load fonts.
|
||||
let fonts = Fonts::load(global_state.i18n.read().fonts(), &mut ui)
|
||||
.expect("Impossible to load fonts!");
|
||||
@ -1380,6 +1383,7 @@ impl Hud {
|
||||
world_map,
|
||||
rot_imgs,
|
||||
item_imgs,
|
||||
item_l10n,
|
||||
fonts,
|
||||
ids,
|
||||
failed_block_pickups: HashMap::default(),
|
||||
@ -2008,7 +2012,7 @@ impl Hud {
|
||||
|
||||
// Item
|
||||
overitem::Overitem::new(
|
||||
item.describe().into(),
|
||||
util::describe(item, i18n, &self.item_l10n).into(),
|
||||
quality,
|
||||
distance,
|
||||
fonts,
|
||||
@ -2091,20 +2095,27 @@ impl Hud {
|
||||
)]
|
||||
},
|
||||
BlockInteraction::Unlock(kind) => {
|
||||
let item_name = |item_id: &ItemDefinitionIdOwned| {
|
||||
item_id
|
||||
.as_ref()
|
||||
.itemdef_id()
|
||||
.map(|id| {
|
||||
let item = Item::new_from_asset_expect(id);
|
||||
util::describe(&item, i18n, &self.item_l10n)
|
||||
})
|
||||
.unwrap_or_else(|| "modular item".to_string())
|
||||
};
|
||||
|
||||
vec![(Some(GameInput::Interact), match kind {
|
||||
UnlockKind::Free => i18n.get_msg("hud-open").to_string(),
|
||||
UnlockKind::Requires(item) => i18n
|
||||
UnlockKind::Requires(item_id) => i18n
|
||||
.get_msg_ctx("hud-unlock-requires", &i18n::fluent_args! {
|
||||
"item" => item.as_ref().itemdef_id()
|
||||
.map(|id| Item::new_from_asset_expect(id).describe())
|
||||
.unwrap_or_else(|| "modular item".to_string()),
|
||||
"item" => item_name(item_id),
|
||||
})
|
||||
.to_string(),
|
||||
UnlockKind::Consumes(item) => i18n
|
||||
UnlockKind::Consumes(item_id) => i18n
|
||||
.get_msg_ctx("hud-unlock-requires", &i18n::fluent_args! {
|
||||
"item" => item.as_ref().itemdef_id()
|
||||
.map(|id| Item::new_from_asset_expect(id).describe())
|
||||
.unwrap_or_else(|| "modular item".to_string()),
|
||||
"item" => item_name(item_id),
|
||||
})
|
||||
.to_string(),
|
||||
})]
|
||||
@ -3166,6 +3177,7 @@ impl Hud {
|
||||
item_tooltip_manager,
|
||||
&mut self.slot_manager,
|
||||
i18n,
|
||||
&self.item_l10n,
|
||||
&msm,
|
||||
self.floaters.combo_floater,
|
||||
&context,
|
||||
@ -3213,6 +3225,7 @@ impl Hud {
|
||||
&mut self.slot_manager,
|
||||
self.pulse,
|
||||
i18n,
|
||||
&self.item_l10n,
|
||||
player_stats,
|
||||
skill_set,
|
||||
health,
|
||||
@ -3257,6 +3270,7 @@ impl Hud {
|
||||
item_tooltip_manager,
|
||||
&mut self.slot_manager,
|
||||
i18n,
|
||||
&self.item_l10n,
|
||||
&msm,
|
||||
self.pulse,
|
||||
&mut self.show,
|
||||
@ -3337,6 +3351,7 @@ impl Hud {
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
i18n,
|
||||
&self.item_l10n,
|
||||
self.pulse,
|
||||
&self.rot_imgs,
|
||||
item_tooltip_manager,
|
||||
@ -3503,6 +3518,7 @@ impl Hud {
|
||||
&self.rot_imgs,
|
||||
&self.fonts,
|
||||
i18n,
|
||||
&self.item_l10n,
|
||||
&msm,
|
||||
item_tooltip_manager,
|
||||
self.pulse,
|
||||
|
@ -19,7 +19,6 @@ use crate::{
|
||||
GlobalState,
|
||||
};
|
||||
use i18n::Localization;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use client::{self, Client};
|
||||
use common::comp::{
|
||||
@ -27,7 +26,7 @@ use common::comp::{
|
||||
ability::{AbilityInput, Stance},
|
||||
item::{
|
||||
tool::{AbilityContext, ToolKind},
|
||||
ItemDesc, MaterialStatManifest,
|
||||
ItemDesc, ItemL10n, MaterialStatManifest,
|
||||
},
|
||||
skillset::SkillGroupKind,
|
||||
Ability, ActiveAbilities, Body, CharacterState, Combo, Energy, Health, Inventory, Poise,
|
||||
@ -308,6 +307,7 @@ pub struct Skillbar<'a> {
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
slot_manager: &'a mut slots::SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
pulse: f32,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
@ -344,6 +344,7 @@ impl<'a> Skillbar<'a> {
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
slot_manager: &'a mut slots::SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
msm: &'a MaterialStatManifest,
|
||||
combo_floater: Option<ComboFloater>,
|
||||
context: &'a AbilityContext,
|
||||
@ -375,6 +376,7 @@ impl<'a> Skillbar<'a> {
|
||||
item_tooltip_manager,
|
||||
slot_manager,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
msm,
|
||||
combo_floater,
|
||||
context,
|
||||
@ -1008,6 +1010,7 @@ impl<'a> Skillbar<'a> {
|
||||
self.pulse,
|
||||
self.msm,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
)
|
||||
.title_font_size(self.fonts.cyri.scale(20))
|
||||
.parent(ui.window)
|
||||
@ -1028,9 +1031,12 @@ impl<'a> Skillbar<'a> {
|
||||
let (hotbar, inventory, _, skill_set, active_abilities, _, contexts, _, _, _) =
|
||||
content_source;
|
||||
hotbar.get(slot).and_then(|content| match content {
|
||||
hotbar::SlotContents::Inventory(i, _) => inventory
|
||||
.get_by_hash(i)
|
||||
.map(|item| (item.name(), Cow::Borrowed(item.description()))),
|
||||
hotbar::SlotContents::Inventory(i, _) => inventory.get_by_hash(i).map(|item| {
|
||||
let (title, desc) =
|
||||
util::item_text(item, self.localized_strings, self.item_l10n);
|
||||
|
||||
(title.into(), desc.into())
|
||||
}),
|
||||
hotbar::SlotContents::Ability(i) => active_abilities
|
||||
.and_then(|a| {
|
||||
a.auxiliary_set(Some(inventory), Some(skill_set))
|
||||
|
@ -10,7 +10,7 @@ use vek::*;
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{
|
||||
inventory::item::{ItemDesc, MaterialStatManifest, Quality},
|
||||
inventory::item::{ItemDesc, ItemL10n, MaterialStatManifest, Quality},
|
||||
Inventory, Stats,
|
||||
},
|
||||
trade::{PendingTrade, SitePrices, TradeAction, TradePhase},
|
||||
@ -35,7 +35,8 @@ use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::ItemImgs,
|
||||
slots::{SlotKind, SlotManager, TradeSlot},
|
||||
Hud, HudInfo, Show, TradeAmountInput, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||
util, Hud, HudInfo, Show, TradeAmountInput, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0,
|
||||
UI_MAIN,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
@ -98,6 +99,7 @@ pub struct Trade<'a> {
|
||||
common: widget::CommonBuilder,
|
||||
slot_manager: &'a mut SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
msm: &'a MaterialStatManifest,
|
||||
pulse: f32,
|
||||
show: &'a mut Show,
|
||||
@ -116,6 +118,7 @@ impl<'a> Trade<'a> {
|
||||
item_tooltip_manager: &'a mut ItemTooltipManager,
|
||||
slot_manager: &'a mut SlotManager,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
msm: &'a MaterialStatManifest,
|
||||
pulse: f32,
|
||||
show: &'a mut Show,
|
||||
@ -132,6 +135,7 @@ impl<'a> Trade<'a> {
|
||||
common: widget::CommonBuilder::default(),
|
||||
slot_manager,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
msm,
|
||||
pulse,
|
||||
show,
|
||||
@ -345,6 +349,7 @@ impl<'a> Trade<'a> {
|
||||
self.pulse,
|
||||
self.msm,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
)
|
||||
.title_font_size(self.fonts.cyri.scale(20))
|
||||
.parent(ui.window)
|
||||
@ -362,6 +367,7 @@ impl<'a> Trade<'a> {
|
||||
self.slot_manager,
|
||||
self.pulse,
|
||||
self.localized_strings,
|
||||
self.item_l10n,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
@ -530,7 +536,11 @@ impl<'a> Trade<'a> {
|
||||
let itemname = slot
|
||||
.invslot
|
||||
.and_then(|i| inventory.get(i))
|
||||
.map(|i| i.name())
|
||||
.map(|i| {
|
||||
let (name, _) = util::item_text(&i, self.localized_strings, self.item_l10n);
|
||||
|
||||
Cow::Owned(name)
|
||||
})
|
||||
.unwrap_or(Cow::Borrowed(""));
|
||||
let is_present = slot.quantity > 0 && slot.invslot.is_some();
|
||||
Text::new(&format!("{} x {}", slot.quantity, itemname))
|
||||
|
@ -5,7 +5,7 @@ use common::{
|
||||
item::{
|
||||
armor::{Armor, ArmorKind, Protection},
|
||||
tool::{Hands, Tool, ToolKind},
|
||||
Effects, Item, ItemDefinitionId, ItemDesc, ItemKind, MaterialKind,
|
||||
Effects, Item, ItemDefinitionId, ItemDesc, ItemKind, ItemL10n, MaterialKind,
|
||||
MaterialStatManifest,
|
||||
},
|
||||
BuffKind,
|
||||
@ -15,7 +15,7 @@ use common::{
|
||||
};
|
||||
use conrod_core::image;
|
||||
use i18n::{fluent_args, Localization};
|
||||
use std::{borrow::Cow, fmt::Write};
|
||||
use std::{borrow::Cow, fmt::Write, num::NonZeroU32};
|
||||
|
||||
pub fn price_desc<'a>(
|
||||
prices: &Option<SitePrices>,
|
||||
@ -61,6 +61,31 @@ pub fn price_desc<'a>(
|
||||
Some((buy_string, sell_string, deal_goodness))
|
||||
}
|
||||
|
||||
pub fn item_text<'a, I: ItemDesc + ?Sized>(
|
||||
item: &I,
|
||||
i18n: &'a Localization,
|
||||
l10n_spec: &'a ItemL10n,
|
||||
) -> (String, String) {
|
||||
let (title, desc) = item.l10n(l10n_spec);
|
||||
|
||||
(i18n.get_content(&title), i18n.get_content(&desc))
|
||||
}
|
||||
|
||||
pub fn describe<'a, I: ItemDesc + ?Sized>(
|
||||
item: &I,
|
||||
i18n: &'a Localization,
|
||||
l10n_spec: &'a ItemL10n,
|
||||
) -> String {
|
||||
let (title, _) = item_text(item, i18n, l10n_spec);
|
||||
let amount = item.amount();
|
||||
|
||||
if amount > NonZeroU32::new(1).unwrap() {
|
||||
format!("{amount} x {title}")
|
||||
} else {
|
||||
title
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind_text<'a>(kind: &ItemKind, i18n: &'a Localization) -> Cow<'a, str> {
|
||||
match kind {
|
||||
ItemKind::Armor(armor) => armor_kind(armor, i18n),
|
||||
|
@ -10,7 +10,7 @@ use common::{
|
||||
comp::{
|
||||
item::{
|
||||
armor::Protection, item_key::ItemKey, modular::ModularComponent, Item, ItemDesc,
|
||||
ItemKind, ItemTag, MaterialStatManifest, Quality,
|
||||
ItemKind, ItemL10n, ItemTag, MaterialStatManifest, Quality,
|
||||
},
|
||||
Energy,
|
||||
},
|
||||
@ -296,6 +296,7 @@ pub struct ItemTooltip<'a> {
|
||||
item_imgs: &'a ItemImgs,
|
||||
pulse: f32,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, WidgetStyle)]
|
||||
@ -360,6 +361,7 @@ impl<'a> ItemTooltip<'a> {
|
||||
pulse: f32,
|
||||
msm: &'a MaterialStatManifest,
|
||||
localized_strings: &'a Localization,
|
||||
item_l10n: &'a ItemL10n,
|
||||
) -> Self {
|
||||
ItemTooltip {
|
||||
common: widget::CommonBuilder::default(),
|
||||
@ -377,6 +379,7 @@ impl<'a> ItemTooltip<'a> {
|
||||
item_imgs,
|
||||
pulse,
|
||||
localized_strings,
|
||||
item_l10n,
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,6 +453,7 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
} = args;
|
||||
|
||||
let i18n = &self.localized_strings;
|
||||
let item_l10n = &self.item_l10n;
|
||||
|
||||
let inventories = self.client.inventories();
|
||||
let inventory = match inventories.get(self.info.viewpoint_entity) {
|
||||
@ -465,7 +469,7 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
|
||||
let equipped_item = inventory.equipped_items_replaceable_by(item_kind).next();
|
||||
|
||||
let (title, desc) = (item.name().to_string(), item.description().to_string());
|
||||
let (title, desc) = util::item_text(item, i18n, item_l10n);
|
||||
|
||||
let item_kind = util::kind_text(item_kind, i18n).to_string();
|
||||
|
||||
@ -1266,7 +1270,8 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
fn default_y_dimension(&self, ui: &Ui) -> Dimension {
|
||||
let item = &self.item;
|
||||
|
||||
let desc = item.description().to_string();
|
||||
// TODO: we do double work here, does it need optimization?
|
||||
let (_, desc) = util::item_text(item, self.localized_strings, self.item_l10n);
|
||||
|
||||
let (text_w, _image_w) = self.text_image_width(260.0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user