Make the new tooltip item specific

This commit is contained in:
Snowram 2021-03-16 13:19:31 +01:00 committed by Robin Gilh
parent 4786f84afd
commit aa71dcb9c7
11 changed files with 520 additions and 149 deletions

Binary file not shown.

View File

@ -78,8 +78,8 @@ impl PartialOrd for Protection {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (*self, *other) {
(Protection::Invincible, Protection::Invincible) => Some(Ordering::Equal),
(Protection::Invincible, _) => Some(Ordering::Less),
(_, Protection::Invincible) => Some(Ordering::Greater),
(Protection::Invincible, _) => Some(Ordering::Greater),
(_, Protection::Invincible) => Some(Ordering::Less),
(Protection::Normal(a), Protection::Normal(b)) => f32::partial_cmp(&a, &b),
}
}

View File

@ -12,7 +12,8 @@ use crate::{
ui::{
fonts::Fonts,
slot::{ContentSize, SlotMaker},
ImageFrame, Tooltip, TooltipManager, Tooltipable, ItemTooltip, ItemTooltipManager, ItemTooltipable,
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
Tooltipable,
},
};
use client::Client;
@ -71,6 +72,7 @@ pub struct InventoryScroller<'a> {
#[conrod(common_builder)]
common: widget::CommonBuilder,
tooltip_manager: &'a mut TooltipManager,
item_tooltip_manager: &'a mut ItemTooltipManager,
slot_manager: &'a mut SlotManager,
pulse: f32,
localized_strings: &'a Localization,
@ -79,6 +81,7 @@ pub struct InventoryScroller<'a> {
msm: &'a MaterialStatManifest,
on_right: bool,
item_tooltip: &'a Tooltip<'a>,
item_tooltip2: &'a ItemTooltip<'a>,
playername: String,
is_us: bool,
inventory: &'a Inventory,
@ -93,6 +96,7 @@ impl<'a> InventoryScroller<'a> {
item_imgs: &'a ItemImgs,
fonts: &'a Fonts,
tooltip_manager: &'a mut TooltipManager,
item_tooltip_manager: &'a mut ItemTooltipManager,
slot_manager: &'a mut SlotManager,
pulse: f32,
localized_strings: &'a Localization,
@ -101,6 +105,7 @@ impl<'a> InventoryScroller<'a> {
msm: &'a MaterialStatManifest,
on_right: bool,
item_tooltip: &'a Tooltip<'a>,
item_tooltip2: &'a ItemTooltip<'a>,
playername: String,
is_us: bool,
inventory: &'a Inventory,
@ -113,6 +118,7 @@ impl<'a> InventoryScroller<'a> {
fonts,
common: widget::CommonBuilder::default(),
tooltip_manager,
item_tooltip_manager,
slot_manager,
pulse,
localized_strings,
@ -121,6 +127,7 @@ impl<'a> InventoryScroller<'a> {
msm,
on_right,
item_tooltip,
item_tooltip2,
playername,
is_us,
inventory,
@ -312,11 +319,17 @@ impl<'a> InventoryScroller<'a> {
slot_widget
.filled_slot(quality_col_img)
.with_tooltip(
self.tooltip_manager,
.with_item_tooltip(
self.item_tooltip_manager,
self.client,
self.imgs,
self.item_imgs,
self.pulse,
title,
&*desc,
self.item_tooltip,
Some(item.clone()),
self.msm,
self.item_tooltip2,
quality_col,
)
.set(state.ids.inv_slots[i], ui);
@ -582,19 +595,26 @@ impl<'a> Widget for Bag<'a> {
.desc_text_color(TEXT_COLOR);
// Tooltips
let item_tooltip2 = 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,
)
})
.title_font_size(self.fonts.cyri.scale(15))
let item_tooltip2 = 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,
self.imgs,
self.item_imgs,
self.pulse,
self.msm,
)
.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)
@ -606,6 +626,7 @@ impl<'a> Widget for Bag<'a> {
self.item_imgs,
self.fonts,
self.tooltip_manager,
self.item_tooltip_manager,
self.slot_manager,
self.pulse,
self.localized_strings,
@ -614,6 +635,7 @@ impl<'a> Widget for Bag<'a> {
self.msm,
true,
&item_tooltip,
&item_tooltip2,
self.stats.name.to_string(),
true,
&inventory,
@ -782,23 +804,34 @@ impl<'a> Widget for Bag<'a> {
|| (i18n.get("hud.bag.head"), ""),
&self.msm,
);
let head_item = inventory
.equipped(EquipSlot::Armor(ArmorSlot::Head))
.map(|item| item.to_owned());
let head_q_col = inventory
.equipped(EquipSlot::Armor(ArmorSlot::Head))
.map(|item| get_quality_col(item))
.unwrap_or(QUALITY_COMMON);
slot_maker
let slot = slot_maker
.fabricate(EquipSlot::Armor(ArmorSlot::Head), [45.0; 2])
.mid_top_with_margin_on(state.bg_ids.bg_frame, 60.0)
.with_icon(self.imgs.head_bg, Vec2::new(32.0, 40.0), Some(UI_MAIN))
.filled_slot(filled_slot)
.with_tooltip(
self.tooltip_manager,
title,
&*desc,
&item_tooltip,
head_q_col,
)
.set(state.ids.head_slot, ui);
.filled_slot(filled_slot);
slot.with_item_tooltip(
self.item_tooltip_manager,
self.client,
self.imgs,
self.item_imgs,
self.pulse,
title,
&*desc,
head_item,
self.msm,
&item_tooltip2,
head_q_col,
)
.set(state.ids.head_slot, ui);
// Necklace
let (title, desc) = loadout_slot_text(
inventory.equipped(EquipSlot::Armor(ArmorSlot::Neck)),
@ -829,6 +862,10 @@ impl<'a> Widget for Bag<'a> {
|| (i18n.get("hud.bag.chest"), ""),
&self.msm,
);
let chest_item = inventory
.equipped(EquipSlot::Armor(ArmorSlot::Chest))
.map(|item| item.to_owned());
let chest_q_col = inventory
.equipped(EquipSlot::Armor(ArmorSlot::Chest))
.map(|item| get_quality_col(item))
@ -840,10 +877,16 @@ impl<'a> Widget for Bag<'a> {
.filled_slot(filled_slot)
.with_item_tooltip(
self.item_tooltip_manager,
self.client,
self.imgs,
self.item_imgs,
self.pulse,
title,
&*desc,
chest_item,
self.msm,
&item_tooltip2,
chest_q_col,
head_q_col,
)
.set(state.ids.chest_slot, ui);
// Shoulders

View File

@ -244,9 +244,9 @@ impl<'a> Widget for ItemInfo<'a> {
.resolve_stats(self.msm, equipped_item.components())
.clamp_speed();
let diff = tool_stats - equipped_tool_stats;
let diff1 = util::comparaison(tool_stats.power, equipped_tool_stats.power);
let diff2 = util::comparaison(tool_stats.speed, equipped_tool_stats.speed);
let diff3 = util::comparaison(
let diff1 = util::comparison(tool_stats.power, equipped_tool_stats.power);
let diff2 = util::comparison(tool_stats.speed, equipped_tool_stats.speed);
let diff3 = util::comparison(
tool_stats.poise_strength,
equipped_tool_stats.poise_strength,
);
@ -299,11 +299,11 @@ impl<'a> Widget for ItemInfo<'a> {
if let Some(equipped_item) = equip_slot.cloned().next() {
if let ItemKind::Armor(equipped_armor) = equipped_item.kind() {
let diff = armor.stats - equipped_armor.stats;
let diff1 = util::comparaison(
let diff1 = util::comparison(
&armor.stats.protection,
&equipped_armor.stats.protection,
);
let diff2 = util::comparaison(
let diff2 = util::comparison(
&armor.stats.poise_resilience,
&equipped_armor.stats.poise_resilience,
);
@ -346,7 +346,7 @@ impl<'a> Widget for ItemInfo<'a> {
.depth(3.0)
.w(300.0)
.set(state.ids.desc, ui);
/*let test = widget::Text::new(&desc).w(300.0).get_h(ui);
dbg!(test);*/

View File

@ -7,8 +7,8 @@ mod diary;
mod esc_menu;
mod group;
mod hotbar;
mod img_ids;
mod item_imgs;
pub mod img_ids;
pub mod item_imgs;
mod item_info;
mod map;
mod minimap;
@ -21,7 +21,7 @@ mod skillbar;
mod slots;
mod social;
mod trade;
mod util;
pub mod util;
pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState};
pub use item_imgs::animate_by_pulse;
@ -906,9 +906,10 @@ impl Hud {
) -> Vec<Event> {
span!(_guard, "update_layout", "Hud::update_layout");
let mut events = std::mem::replace(&mut self.events, Vec::new());
let (ref mut ui_widgets, ref mut item_tooltip_manager, ref mut tooltip_manager) = &mut self.ui.set_widgets();
//let (ref mut ui_item_widgets, ref mut item_tooltip_manager) = &mut self.ui.set_item_widgets();
// pulse time for pulsating elements
let (ref mut ui_widgets, ref mut item_tooltip_manager, ref mut tooltip_manager) =
&mut self.ui.set_widgets();
//let (ref mut ui_item_widgets, ref mut item_tooltip_manager) = &mut
// self.ui.set_item_widgets(); pulse time for pulsating elements
self.pulse = self.pulse + dt.as_secs_f32();
// FPS
let fps = global_state.clock.stats().average_tps;
@ -2327,6 +2328,7 @@ impl Hud {
&self.fonts,
&self.rot_imgs,
tooltip_manager,
item_tooltip_manager,
&mut self.slot_manager,
i18n,
&msm,

View File

@ -11,7 +11,8 @@ use crate::{
ui::{
fonts::Fonts,
slot::{ContentSize, SlotMaker},
ImageFrame, Tooltip, TooltipManager, Tooltipable, ItemTooltip, ItemTooltipManager, ItemTooltipable,
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
Tooltipable,
},
window::GameInput,
GlobalState,
@ -485,24 +486,6 @@ impl<'a> Widget for Skillbar<'a> {
.font_id(self.fonts.cyri.conrod_id)
.desc_text_color(TEXT_COLOR);
let item_tooltip2 = 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,
)
})
.title_font_size(self.fonts.cyri.scale(15))
.parent(ui.window)
.desc_font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.desc_text_color(TEXT_COLOR);
// Helper
let tooltip_text = |slot| {
content_source
@ -565,7 +548,7 @@ impl<'a> Widget for Skillbar<'a> {
.filled_slot(self.imgs.skillbar_slot)
.bottom_left_with_margins_on(state.ids.frame, 0.0, 0.0);
if let Some((title, desc)) = tooltip_text(hotbar::Slot::One) {
slot.with_item_tooltip(self.item_tooltip_manager, title, desc, &item_tooltip2, TEXT_COLOR)
slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
.set(state.ids.slot1, ui);
} else {
slot.set(state.ids.slot1, ui);

View File

@ -11,7 +11,7 @@ use crate::{
ui::{
fonts::Fonts,
slot::{ContentSize, SlotMaker},
ImageFrame, Tooltip, TooltipManager, Tooltipable,
ImageFrame, ItemTooltip, ItemTooltipManager, Tooltip, TooltipManager, Tooltipable,
},
};
use client::Client;
@ -64,6 +64,7 @@ pub struct Trade<'a> {
fonts: &'a Fonts,
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
item_tooltip_manager: &'a mut ItemTooltipManager,
#[conrod(common_builder)]
common: widget::CommonBuilder,
slot_manager: &'a mut SlotManager,
@ -80,6 +81,7 @@ impl<'a> Trade<'a> {
fonts: &'a Fonts,
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
item_tooltip_manager: &'a mut ItemTooltipManager,
slot_manager: &'a mut SlotManager,
localized_strings: &'a Localization,
msm: &'a MaterialStatManifest,
@ -92,6 +94,7 @@ impl<'a> Trade<'a> {
fonts,
rot_imgs,
tooltip_manager,
item_tooltip_manager,
common: widget::CommonBuilder::default(),
slot_manager,
localized_strings,
@ -282,6 +285,32 @@ impl<'a> Trade<'a> {
.font_id(self.fonts.cyri.conrod_id)
.desc_text_color(TEXT_COLOR);
// Tooltips
let item_tooltip2 = 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,
self.imgs,
self.item_imgs,
self.pulse,
self.msm,
)
.title_font_size(self.fonts.cyri.scale(15))
.parent(ui.window)
.desc_font_size(self.fonts.cyri.scale(12))
.font_id(self.fonts.cyri.conrod_id)
.desc_text_color(TEXT_COLOR);
if !ours {
InventoryScroller::new(
self.client,
@ -289,6 +318,7 @@ impl<'a> Trade<'a> {
self.item_imgs,
self.fonts,
self.tooltip_manager,
self.item_tooltip_manager,
self.slot_manager,
self.pulse,
self.localized_strings,
@ -297,6 +327,7 @@ impl<'a> Trade<'a> {
self.msm,
false,
&item_tooltip,
&item_tooltip2,
name,
false,
&inventory,

View File

@ -48,9 +48,7 @@ pub fn item_text<'a>(
item.description(),
)),
ItemKind::Glider(_glider) => Cow::Owned(generic_desc(item)),
ItemKind::Consumable { effect, .. } => {
Cow::Owned(consumable_desc(effect, item.description()))
},
ItemKind::Consumable { effect, .. } => Cow::Owned(consumable_desc(effect)),
ItemKind::Throwable { .. } => Cow::Owned(generic_desc(item)),
ItemKind::Utility { .. } => Cow::Owned(generic_desc(item)),
ItemKind::Ingredient { .. } => Cow::Owned(ingredient_desc(
@ -141,9 +139,8 @@ fn modular_component_desc(
result
}
fn consumable_desc(effects: &[Effect], desc: &str) -> String {
// TODO: localization
let mut description = "Consumable".to_string();
pub fn consumable_desc(effects: &[Effect]) -> String {
let mut description = "".to_string();
for effect in effects {
if let Effect::Buff(buff) = effect {
@ -168,7 +165,7 @@ fn consumable_desc(effects: &[Effect], desc: &str) -> String {
| BuffKind::ProtectingWard => continue,
};
write!(&mut description, "\n\n{}", buff_desc).unwrap();
write!(&mut description, "{}", buff_desc).unwrap();
let dur_desc = if dur_secs.is_some() {
match buff.kind {
@ -196,11 +193,6 @@ fn consumable_desc(effects: &[Effect], desc: &str) -> String {
}
}
if !desc.is_empty() {
write!(&mut description, "\n\n{}", desc).unwrap();
}
write!(&mut description, "\n\n<Right-Click to use>").unwrap();
description
}
@ -342,11 +334,7 @@ pub fn tool_desc(
fn statblock_desc(stats: &Stats) -> String {
format!(
"DPS: {:0.1}\nPower: {:0.1}\nSpeed: {:0.1}\n",
// add back when ready for poise
//"{}\n\nDPS: {:0.1}\n\nPower: {:0.1}\n\nPoise Strength: {:0.1}\n\nSpeed: \
// {:0.1}\n\n{}\n\n<Right-Click to use>",
stats.speed * stats.power * 10.0, // Damage per second
"Power: {:0.1}\n\nPoise Strength: {:0.1}\n\nSpeed: {:0.1}\n\n",
stats.power * 10.0,
stats.poise_strength * 10.0,
stats.speed,
@ -358,13 +346,13 @@ fn statblock_desc(stats: &Stats) -> String {
}
// Compare two type, output a colored character to show comparison
pub fn comparaison<T: PartialOrd>(first: T, other: T) -> (String, conrod_core::color::Color) {
pub fn comparison<T: PartialOrd>(first: T, other: T) -> (String, conrod_core::color::Color) {
if first == other {
(".".to_string(), conrod_core::color::GREY)
("".to_string(), conrod_core::color::GREY)
} else if other < first {
("^".to_string(), conrod_core::color::GREEN)
("".to_string(), conrod_core::color::GREEN)
} else {
("v".to_string(), conrod_core::color::RED)
("".to_string(), conrod_core::color::RED)
}
}

View File

@ -16,11 +16,11 @@ pub use widgets::{
image_frame::ImageFrame,
image_slider::ImageSlider,
ingame::{Ingame, Ingameable},
item_tooltip::{ItemTooltip, ItemTooltipManager, ItemTooltipable},
radio_list::RadioList,
slot,
toggle_button::ToggleButton,
tooltip::{Tooltip, TooltipManager, Tooltipable},
item_tooltip::{ItemTooltip, ItemTooltipManager, ItemTooltipable},
};
use crate::{
@ -236,7 +236,11 @@ impl Ui {
pub fn id_generator(&mut self) -> Generator { self.ui.widget_id_generator() }
pub fn set_widgets(&mut self) -> (UiCell, &mut ItemTooltipManager, &mut TooltipManager) {
(self.ui.set_widgets(), &mut self.item_tooltip_manager, &mut self.tooltip_manager)
(
self.ui.set_widgets(),
&mut self.item_tooltip_manager,
&mut self.tooltip_manager,
)
}
pub fn set_item_widgets(&mut self) -> (UiCell, &mut ItemTooltipManager) {

View File

@ -1,10 +1,19 @@
use super::image_frame::ImageFrame;
use crate::hud::{
get_quality_col,
img_ids::Imgs,
item_imgs::{animate_by_pulse, ItemImgs},
util,
};
use client::Client;
use common::comp::item::{Item, ItemKind, MaterialStatManifest, Quality};
use conrod_core::{
builder_method, builder_methods, image, input::global::Global, position::Dimension, text,
widget, widget_ids, Color, Colorable, FontSize, Positionable, Sizeable, Ui, UiCell, Widget,
WidgetCommon, WidgetStyle,
};
use std::time::{Duration, Instant};
#[derive(Copy, Clone)]
struct Hover(widget::Id, [f64; 2]);
#[derive(Copy, Clone)]
@ -96,6 +105,7 @@ impl ItemTooltipManager {
tooltip: &ItemTooltip,
title_text: &str,
desc_text: &str,
item: Option<Item>,
title_col: Color,
img_id: Option<image::Id>,
image_dims: Option<(f64, f64)>,
@ -112,6 +122,7 @@ impl ItemTooltipManager {
.clone()
.title(title_text)
.desc(desc_text)
.item(item)
.title_col(title_col)
.image(img_id)
.image_dims(image_dims);
@ -160,8 +171,14 @@ impl ItemTooltipManager {
pub struct ItemTooltipped<'a, W> {
inner: W,
tooltip_manager: &'a mut ItemTooltipManager,
client: &'a Client,
imgs: &'a Imgs,
item_imgs: &'a ItemImgs,
pulse: f32,
title_text: &'a str,
desc_text: &'a str,
item: Option<Item>,
msm: &'a MaterialStatManifest,
img_id: Option<image::Id>,
image_dims: Option<(f64, f64)>,
tooltip: &'a ItemTooltip<'a>,
@ -184,6 +201,7 @@ impl<'a, W: Widget> ItemTooltipped<'a, W> {
self.tooltip,
self.title_text,
self.desc_text,
self.item,
self.title_col,
self.img_id,
self.image_dims,
@ -199,8 +217,14 @@ pub trait ItemTooltipable {
fn with_item_tooltip<'a>(
self,
tooltip_manager: &'a mut ItemTooltipManager,
client: &'a Client,
imgs: &'a Imgs,
item_imgs: &'a ItemImgs,
pulse: f32,
title_text: &'a str,
desc_text: &'a str,
item: Option<Item>,
msm: &'a MaterialStatManifest,
tooltip: &'a ItemTooltip<'a>,
title_col: Color,
) -> ItemTooltipped<'a, Self>
@ -211,16 +235,28 @@ impl<W: Widget> ItemTooltipable for W {
fn with_item_tooltip<'a>(
self,
tooltip_manager: &'a mut ItemTooltipManager,
client: &'a Client,
imgs: &'a Imgs,
item_imgs: &'a ItemImgs,
pulse: f32,
title_text: &'a str,
desc_text: &'a str,
item: Option<Item>,
msm: &'a MaterialStatManifest,
tooltip: &'a ItemTooltip<'a>,
title_col: Color,
) -> ItemTooltipped<'a, W> {
ItemTooltipped {
inner: self,
tooltip_manager,
client,
imgs,
item_imgs,
pulse,
title_text,
desc_text,
item,
msm,
img_id: None,
image_dims: None,
tooltip,
@ -236,9 +272,11 @@ const H_PAD: f64 = 10.0;
/// Default portion of inner width that goes to an image
const IMAGE_W_FRAC: f64 = 0.3;
/// Default width multiplied by the description font size
const DEFAULT_CHAR_W: f64 = 30.0;
const DEFAULT_CHAR_W: f64 = 20.0;
/// Text vertical spacing factor to account for overhanging text
const TEXT_SPACE_FACTOR: f64 = 0.35;
// Item icon size
const ICON_SIZE: [f64; 2] = [64.0, 64.0];
/// A widget for displaying tooltips
#[derive(Clone, WidgetCommon)]
@ -247,12 +285,18 @@ pub struct ItemTooltip<'a> {
common: widget::CommonBuilder,
title_text: &'a str,
desc_text: &'a str,
item: Option<Item>,
msm: &'a MaterialStatManifest,
title_col: Color,
image: Option<image::Id>,
image_dims: Option<(f64, f64)>,
style: Style,
transparency: f32,
image_frame: ImageFrame,
client: &'a Client,
imgs: &'a Imgs,
item_imgs: &'a ItemImgs,
pulse: f32,
}
#[derive(Clone, Debug, Default, PartialEq, WidgetStyle)]
@ -267,9 +311,23 @@ pub struct Style {
widget_ids! {
struct Ids {
title,
subtitle,
desc,
stat1,
stat2,
stat3,
stat4,
stat5,
diff1,
diff2,
diff3,
diff4,
diff5,
item_frame,
item_render,
image_frame,
image,
background,
}
}
@ -287,22 +345,37 @@ impl<'a> ItemTooltip<'a> {
image { image = Option<image::Id> }
title { title_text = &'a str }
desc { desc_text = &'a str }
item { item = Option<Item> }
msm { msm = &'a MaterialStatManifest }
image_dims { image_dims = Option<(f64, f64)> }
transparency { transparency = f32 }
title_col { title_col = Color}
}
pub fn new(image_frame: ImageFrame) -> Self {
pub fn new(
image_frame: ImageFrame,
client: &'a Client,
imgs: &'a Imgs,
item_imgs: &'a ItemImgs,
pulse: f32,
msm: &'a MaterialStatManifest,
) -> Self {
ItemTooltip {
common: widget::CommonBuilder::default(),
style: Style::default(),
title_text: "",
desc_text: "",
item: None,
msm,
transparency: 1.0,
image_frame,
image: None,
image_dims: None,
title_col: TEXT_COLOR,
client: &client,
imgs: &imgs,
item_imgs: &item_imgs,
pulse,
}
}
@ -375,74 +448,326 @@ impl<'a> Widget for ItemTooltip<'a> {
..
} = args;
// Widths
let (text_w, image_w) = self.text_image_width(rect.w());
if let Some(ref item) = self.item {
let item = item;
// Apply transparency
let color = style.color(ui.theme()).alpha(self.transparency);
let inventories = self.client.inventories();
let inventory = match inventories.get(self.client.entity()) {
Some(l) => l,
None => return,
};
// Background image frame
self.image_frame
.wh(rect.dim())
.xy(rect.xy())
.graphics_for(id)
.parent(id)
.color(color)
.set(state.ids.image_frame, ui);
let quality = get_quality_col(item);
// Image
if let Some(img_id) = self.image {
widget::Image::new(img_id)
.w_h(image_w, self.image_dims.map_or(image_w, |(_, h)| h))
let equip_slot = inventory.equipped_items_of_kind(item.kind().clone());
let (title, desc) = (item.name().to_string(), item.description().to_string());
let subtitle = util::kind_text(item.kind());
let text_color = conrod_core::color::WHITE;
// Widths
let (text_w, image_w) = self.text_image_width(rect.w());
// Apply transparency
let color = style.color(ui.theme()).alpha(self.transparency);
// Color quality
let quality_col_img = match &item.quality() {
Quality::Low => self.imgs.inv_slot_grey,
Quality::Common => self.imgs.inv_slot,
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,
};
// Spacing for overhanging text
let title_space = self.style.title.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR;
//let _i18n = &self.localized_strings;
// Background image frame
self.image_frame
.wh(rect.dim())
.xy(rect.xy())
.graphics_for(id)
.parent(id)
.color(quality)
.set(state.ids.image_frame, ui);
// Image
if let Some(img_id) = self.image {
widget::Image::new(img_id)
.w_h(image_w, self.image_dims.map_or(image_w, |(_, h)| h))
.graphics_for(id)
.parent(id)
.color(Some(quality))
.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
.set(state.ids.image, ui);
}
// Icon BG
widget::Image::new(quality_col_img)
.wh(ICON_SIZE)
.graphics_for(id)
.parent(id)
.color(Some(color))
.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
.set(state.ids.image, ui);
}
.set(state.ids.item_frame, ui);
// Spacing for overhanging text
let title_space = self.style.title.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR;
// Icon
widget::Image::new(animate_by_pulse(
&self.item_imgs.img_ids_or_not_found_img(item.into()),
self.pulse,
))
.color(Some(conrod_core::color::WHITE))
.w_h(ICON_SIZE[0] * 0.8, ICON_SIZE[1] * 0.8)
.middle_of(state.ids.item_frame)
.set(state.ids.item_render, ui);
// Title of tooltip
if !self.title_text.is_empty() {
let title = widget::Text::new(self.title_text)
// Title
let title = widget::Text::new(&title)
.w(text_w)
.graphics_for(id)
.parent(id)
.with_style(self.style.title)
// Apply transparency
.color(self.title_col);
.color(quality);
if self.image.is_some() {
title
.right_from(state.ids.image, H_PAD)
.align_top_of(state.ids.image)
} else {
title.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
title.right_from(state.ids.item_frame, 10.0)
}
.set(state.ids.title, ui);
}
// Description of tooltip
let desc = widget::Text::new(self.desc_text)
.w(text_w)
.graphics_for(id)
.parent(id)
// Apply transparency
.color(style.desc.color(ui.theme()).alpha(self.transparency))
.with_style(self.style.desc);
// Subtitle
widget::Text::new(&subtitle)
.w(text_w)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(conrod_core::color::GREY)
.down_from(state.ids.title, H_PAD)
.set(state.ids.subtitle, ui);
if !self.title_text.is_empty() {
desc.down_from(state.ids.title, V_PAD * 0.5 + title_space)
.align_left_of(state.ids.title)
} else if self.image.is_some() {
desc.right_from(state.ids.image, H_PAD)
.align_top_of(state.ids.image)
} else {
desc.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
// Stats
match item.kind() {
ItemKind::Tool(tool) => {
let stat1 = tool.base_power(self.msm, item.components()) * 10.0;
let stat2 = tool.base_speed(self.msm, item.components());
let stat3 = tool.base_poise_strength(self.msm, item.components()) * 10.0;
let stat4 = tool.base_crit_chance(self.msm, item.components()) * 100.0;
let stat5 = tool.base_crit_mult(self.msm, item.components());
widget::Text::new(&format!("Power : {:.1}", stat1))
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.down_from(state.ids.item_frame, H_PAD)
.set(state.ids.stat1, ui);
widget::Text::new(&format!("Speed : {:.1}", stat2))
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.set(state.ids.stat2, ui);
widget::Text::new(&format!("Poise : {:.1}", stat3))
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.set(state.ids.stat3, ui);
widget::Text::new(&format!("Crit Chance : {:.1}%", stat4))
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.set(state.ids.stat4, ui);
widget::Text::new(&format!("Crit Mult : x{:.1}", stat5))
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.set(state.ids.stat5, ui);
if let Some(equipped_item) = equip_slot.cloned().next() {
if let ItemKind::Tool(equipped_tool) = equipped_item.kind() {
let tool_stats = tool
.stats
.resolve_stats(self.msm, item.components())
.clamp_speed();
let equipped_tool_stats = equipped_tool
.stats
.resolve_stats(self.msm, equipped_item.components())
.clamp_speed();
let diff = tool_stats - equipped_tool_stats;
let diff1 =
util::comparison(tool_stats.power, equipped_tool_stats.power);
let diff2 =
util::comparison(tool_stats.speed, equipped_tool_stats.speed);
let diff3 = util::comparison(
tool_stats.poise_strength,
equipped_tool_stats.poise_strength,
);
let diff4 = util::comparison(
tool_stats.crit_chance,
equipped_tool_stats.crit_chance,
);
let diff5 = util::comparison(
tool_stats.crit_mult,
equipped_tool_stats.crit_mult,
);
widget::Text::new(&format!("{} {:.1}", &diff1.0, &diff.power * 10.0))
.align_middle_y_of(state.ids.stat1)
.right_from(state.ids.stat1, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff1.1)
.h(2.0)
.set(state.ids.diff1, ui);
widget::Text::new(&format!("{} {:.1}", &diff2.0, &diff.speed))
.align_middle_y_of(state.ids.stat2)
.right_from(state.ids.stat2, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff2.1)
.h(2.0)
.set(state.ids.diff2, ui);
widget::Text::new(&format!(
"{} {:.1}",
&diff3.0,
&diff.poise_strength * 10.0
))
.align_middle_y_of(state.ids.stat3)
.right_from(state.ids.stat3, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff3.1)
.h(2.0)
.set(state.ids.diff3, ui);
widget::Text::new(&format!("{} {:.1}%", &diff4.0, &diff.crit_chance * 100.0))
.align_middle_y_of(state.ids.stat4)
.right_from(state.ids.stat4, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff4.1)
.h(2.0)
.set(state.ids.diff4, ui);
widget::Text::new(&format!("{} {:.1}", &diff5.0, &diff.crit_mult))
.align_middle_y_of(state.ids.stat5)
.right_from(state.ids.stat5, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff5.1)
.h(2.0)
.set(state.ids.diff5, ui);
}
}
},
ItemKind::Armor(armor) => {
let stat1 = armor.get_protection();
let stat2 = armor.get_poise_resilience();
widget::Text::new(&format!("Armour : {}", util::protec2string(stat1)))
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.down_from(state.ids.item_frame, H_PAD)
.set(state.ids.stat1, ui);
widget::Text::new(&format!("Poise res : {}", util::protec2string(stat2)))
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.set(state.ids.stat2, ui);
if let Some(equipped_item) = equip_slot.cloned().next() {
if let ItemKind::Armor(equipped_armor) = equipped_item.kind() {
let diff = armor.stats - equipped_armor.stats;
let diff1 = util::comparison(
&armor.stats.protection,
&equipped_armor.stats.protection,
);
let diff2 = util::comparison(
&armor.stats.poise_resilience,
&equipped_armor.stats.poise_resilience,
);
widget::Text::new(&format!(
"{} {}",
&diff1.0,
util::protec2string(diff.protection)
))
.align_middle_y_of(state.ids.stat1)
.right_from(state.ids.stat1, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff1.1)
.h(2.0)
.set(state.ids.diff1, ui);
widget::Text::new(&format!(
"{} {}",
&diff2.0,
util::protec2string(diff.poise_resilience)
))
.align_middle_y_of(state.ids.stat2)
.right_from(state.ids.stat2, 10.0)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(diff2.1)
.h(2.0)
.set(state.ids.diff2, ui);
}
}
},
ItemKind::Consumable { effect, .. } => {
dbg!(&util::consumable_desc(effect));
widget::Text::new(&util::consumable_desc(effect))
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(text_color)
.h(2.0)
.down_from(state.ids.item_frame, H_PAD)
.set(state.ids.stat1, ui);
},
_ => (),
}
widget::Text::new(&desc)
.w(text_w)
.x_align_to(state.ids.item_frame, conrod_core::position::Align::Start)
.graphics_for(id)
.parent(id)
.with_style(self.style.desc)
.color(conrod_core::color::GREY)
.w(text_w)
.set(state.ids.desc, ui);
}
.set(state.ids.desc, ui);
}
/// Default width is based on the description font size unless the text is
@ -474,17 +799,12 @@ impl<'a> Widget for ItemTooltip<'a> {
fn default_y_dimension(&self, ui: &Ui) -> Dimension {
let (text_w, image_w) = self.text_image_width(self.get_w(ui).unwrap_or(0.0));
let title_h = if self.title_text.is_empty() {
0.0
} else {
widget::Text::new(self.title_text)
.with_style(self.style.title)
.w(text_w)
.get_h(ui)
.unwrap_or(0.0)
+ self.style.title.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR
+ 0.5 * V_PAD
};
let icone_h = widget::Image::new(self.imgs.inv_slot_grey)
.wh(ICON_SIZE)
.get_h(ui)
.unwrap_or(0.0);
let desc_h = if self.desc_text.is_empty() {
0.0
} else {
@ -498,11 +818,11 @@ impl<'a> Widget for ItemTooltip<'a> {
// Image defaults to square shape
let image_h = self.image_dims.map_or(image_w, |(_, h)| h);
// Title height + desc height + padding/spacing
let height = (title_h + desc_h).max(image_h) + 2.0 * V_PAD;
let height = (icone_h + desc_h).max(image_h) + 2.0 * V_PAD;
Dimension::Absolute(height)
}
}
impl<'a> Colorable for ItemTooltip<'a> {
builder_method!(color { style.color = Some(Color) });
}
}

View File

@ -2,8 +2,8 @@ pub mod ghost_image;
pub mod image_frame;
pub mod image_slider;
pub mod ingame;
pub mod item_tooltip;
pub mod radio_list;
pub mod slot;
pub mod toggle_button;
pub mod tooltip;
pub mod item_tooltip;