From cae5313127481eea77958ab1ea60a04473e66b93 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 11 Apr 2020 21:20:48 -0400 Subject: [PATCH] tooltips for the skillbar --- voxygen/src/hud/mod.rs | 3 + voxygen/src/hud/skillbar.rs | 221 +++++++++++++++++++++--------- voxygen/src/ui/widgets/tooltip.rs | 14 +- 3 files changed, 170 insertions(+), 68 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 93899d73b8..1f713de20e 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1703,6 +1703,7 @@ impl Hud { &self.imgs, &self.item_imgs, &self.fonts, + &self.rot_imgs, &stats, &loadout, &energy, @@ -1711,7 +1712,9 @@ impl Hud { &controller, &inventory, &self.hotbar, + tooltip_manager, &mut self.slot_manager, + &self.voxygen_i18n, ) .set(self.ids.skillbar, ui_widgets); } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index e8bb9f3dce..11dd6ed3db 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -1,25 +1,26 @@ use super::{ - hotbar, img_ids::Imgs, item_imgs::ItemImgs, slots, BarNumbers, ShortcutNumbers, XpBar, BLACK, - CRITICAL_HP_COLOR, HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR, + hotbar, + img_ids::{Imgs, ImgsRot}, + item_imgs::ItemImgs, + slots, BarNumbers, ShortcutNumbers, XpBar, BLACK, CRITICAL_HP_COLOR, HP_COLOR, LOW_HP_COLOR, + MANA_COLOR, TEXT_COLOR, XP_COLOR, }; use crate::{ - i18n::{i18n_asset_key, VoxygenLocalization}, + i18n::VoxygenLocalization, ui::{ fonts::ConrodVoxygenFonts, slot::{ContentSize, SlotMaker}, + ImageFrame, Tooltip, TooltipManager, Tooltipable, }, window::GameInput, GlobalState, }; -use common::{ - assets::load_expect, - comp::{ - item::{ - tool::{DebugKind, StaffKind, Tool, ToolKind}, - ItemKind, - }, - CharacterState, ControllerInputs, Energy, Inventory, Loadout, Stats, +use common::comp::{ + item::{ + tool::{DebugKind, StaffKind, Tool, ToolKind}, + ItemKind, }, + CharacterState, ControllerInputs, Energy, Inventory, Loadout, Stats, }; use conrod_core::{ color, @@ -64,45 +65,34 @@ widget_ids! { m2_slot_act, m2_content, slot1, - slot1_bg, slot1_text, slot1_text_bg, - slot1_icon, - slot1_act, + //slot1_act, slot2, - slot2_bg, slot2_text, slot2_text_bg, slot3, - slot3_bg, slot3_text, slot3_text_bg, slot4, - slot4_bg, slot4_text, slot4_text_bg, slot5, - slot5_bg, slot5_text, slot5_text_bg, slot6, - slot6_bg, slot6_text, slot6_text_bg, slot7, - slot7_bg, slot7_text, slot7_text_bg, slot8, - slot8_bg, slot8_text, slot8_text_bg, slot9, - slot9_bg, slot9_text, slot9_text_bg, slot10, - slot10_bg, slot10_text, slot10_text_bg, healthbar_bg, @@ -135,6 +125,7 @@ pub struct Skillbar<'a> { imgs: &'a Imgs, item_imgs: &'a ItemImgs, fonts: &'a ConrodVoxygenFonts, + rot_imgs: &'a ImgsRot, stats: &'a Stats, loadout: &'a Loadout, energy: &'a Energy, @@ -142,7 +133,9 @@ pub struct Skillbar<'a> { controller: &'a ControllerInputs, inventory: &'a Inventory, hotbar: &'a hotbar::State, + tooltip_manager: &'a mut TooltipManager, slot_manager: &'a mut slots::SlotManager, + localized_strings: &'a std::sync::Arc, pulse: f32, #[conrod(common_builder)] common: widget::CommonBuilder, @@ -155,6 +148,7 @@ impl<'a> Skillbar<'a> { imgs: &'a Imgs, item_imgs: &'a ItemImgs, fonts: &'a ConrodVoxygenFonts, + rot_imgs: &'a ImgsRot, stats: &'a Stats, loadout: &'a Loadout, energy: &'a Energy, @@ -163,13 +157,16 @@ impl<'a> Skillbar<'a> { controller: &'a ControllerInputs, inventory: &'a Inventory, hotbar: &'a hotbar::State, + tooltip_manager: &'a mut TooltipManager, slot_manager: &'a mut slots::SlotManager, + localized_strings: &'a std::sync::Arc, ) -> Self { Self { global_state, imgs, item_imgs, fonts, + rot_imgs, stats, loadout, energy, @@ -180,7 +177,9 @@ impl<'a> Skillbar<'a> { controller, inventory, hotbar, + tooltip_manager, slot_manager, + localized_strings, } } } @@ -234,9 +233,7 @@ impl<'a> Widget for Skillbar<'a> { let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); - let localized_strings = load_expect::(&i18n_asset_key( - &self.global_state.settings.language.selected_language, - )); + let localized_strings = self.localized_strings; // Stamina Wheel /* @@ -821,26 +818,82 @@ impl<'a> Widget for Skillbar<'a> { image_source: &image_source, slot_manager: Some(self.slot_manager), }; + let item_tooltip = Tooltip::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)) + .title_text_color(TEXT_COLOR) + .font_id(self.fonts.cyri.conrod_id) + .desc_text_color(TEXT_COLOR); + // Helper + let tooltip_text = |slot| { + content_source + .0 + .get(slot) + .and_then(|content| match content { + hotbar::SlotContents::Inventory(i) => content_source + .1 + .get(i) + .map(|item| (item.name(), item.description())), + hotbar::SlotContents::Ability3 => Some(("Something something fireball", "")), + }) + }; + const SLOT_TOOLTIP_UPSHIFT: f64 = 70.0; //Slot 5 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Five, [20.0 * scale as f32; 2]) - .bottom_left_with_margins_on(state.ids.m1_slot, 0.0, -20.0 * scale) - .set(state.ids.slot5, ui); + .bottom_left_with_margins_on(state.ids.m1_slot, 0.0, -20.0 * scale); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Five) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot5, ui); + } else { + slot.set(state.ids.slot5, ui); + } // Slot 4 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Four, [20.0 * scale as f32; 2]) - .left_from(state.ids.slot5, 0.0) - .set(state.ids.slot4, ui); + .left_from(state.ids.slot5, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Four) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot4, ui); + } else { + slot.set(state.ids.slot4, ui); + } // Slot 3 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Three, [20.0 * scale as f32; 2]) - .left_from(state.ids.slot4, 0.0) - .set(state.ids.slot3, ui); + .left_from(state.ids.slot4, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot3, ui); + } else { + slot.set(state.ids.slot3, ui); + } // Slot 2 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Two, [20.0 * scale as f32; 2]) - .left_from(state.ids.slot3, 0.0) - .set(state.ids.slot2, ui); + .left_from(state.ids.slot3, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Two) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot2, ui); + } else { + slot.set(state.ids.slot2, ui); + } // Slot 1 // TODO: Don't hardcode this to one Skill... // Frame flashes whenever the active skill inside this slot is activated @@ -864,10 +917,16 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.slot1_act, ui); }, }*/ - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::One, [20.0 * scale as f32; 2]) - .left_from(state.ids.slot2, 0.0) - .set(state.ids.slot1, ui); + .left_from(state.ids.slot2, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::One) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot1, ui); + } else { + slot.set(state.ids.slot1, ui); + } // TODO: Changeable slot image /*match self.loadout.active_item.as_ref().map(|i| &i.item.kind) { Some(ItemKind::Tool(Tool { kind, .. })) => match kind { @@ -887,33 +946,63 @@ impl<'a> Widget for Skillbar<'a> { _ => {}, }*/ // Slot 6 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Six, [20.0 * scale as f32; 2]) - .bottom_right_with_margins_on(state.ids.m2_slot, 0.0, -20.0 * scale) - .set(state.ids.slot6, ui); + .bottom_right_with_margins_on(state.ids.m2_slot, 0.0, -20.0 * scale); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Six) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot6, ui); + } else { + slot.set(state.ids.slot6, ui); + } // Slot 7 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Seven, [20.0 * scale as f32; 2]) - .right_from(state.ids.slot6, 0.0) - .set(state.ids.slot7, ui); + .right_from(state.ids.slot6, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Seven) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot7, ui); + } else { + slot.set(state.ids.slot7, ui); + } // Slot 8 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Eight, [20.0 * scale as f32; 2]) - .right_from(state.ids.slot7, 0.0) - .set(state.ids.slot8, ui); + .right_from(state.ids.slot7, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Eight) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot8, ui); + } else { + slot.set(state.ids.slot8, ui); + } // Slot 9 - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Nine, [20.0 * scale as f32; 2]) - .right_from(state.ids.slot8, 0.0) - .set(state.ids.slot9, ui); + .right_from(state.ids.slot8, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Nine) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot9, ui); + } else { + slot.set(state.ids.slot9, ui); + } // Quickslot slot_maker.filled_slot = self.imgs.skillbar_slot_r; slot_maker.selected_slot = self.imgs.skillbar_slot_r; slot_maker.empty_slot = self.imgs.skillbar_slot_r; - slot_maker + let slot = slot_maker .fabricate(hotbar::Slot::Ten, [20.0 * scale as f32; 2]) - .right_from(state.ids.slot9, 0.0) - .set(state.ids.slot10, ui); + .right_from(state.ids.slot9, 0.0); + if let Some((title, desc)) = tooltip_text(hotbar::Slot::Ten) { + slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip) + .bottom_offset(SLOT_TOOLTIP_UPSHIFT) + .set(state.ids.slot10, ui); + } else { + slot.set(state.ids.slot10, ui); + } // Shortcuts if let ShortcutNumbers::On = shortcuts { @@ -924,7 +1013,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot1) { Text::new(slot1.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot1_bg, 1.0, 2.0) + .top_right_with_margins_on(state.ids.slot1, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -943,7 +1032,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot2) { Text::new(slot2.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot2_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot2, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -962,7 +1051,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot3) { Text::new(slot3.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot3_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot3, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -981,7 +1070,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot4) { Text::new(slot4.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot4_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot4, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1000,7 +1089,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot5) { Text::new(slot5.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot5_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot5, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1057,7 +1146,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot6) { Text::new(slot6.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot6_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot6, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1076,7 +1165,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot7) { Text::new(slot7.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot7_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot7, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1095,7 +1184,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot8) { Text::new(slot8.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot8_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot8, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1114,7 +1203,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot9) { Text::new(slot9.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot9_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot9, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) @@ -1133,7 +1222,7 @@ impl<'a> Widget for Skillbar<'a> { .get_binding(GameInput::Slot10) { Text::new(slot10.to_string().as_str()) - .top_right_with_margins_on(state.ids.slot10_bg, 1.0, 1.0) + .top_right_with_margins_on(state.ids.slot10, 2.0, 2.0) .font_size(self.fonts.cyri.scale(8)) .font_id(self.fonts.cyri.conrod_id) .color(BLACK) diff --git a/voxygen/src/ui/widgets/tooltip.rs b/voxygen/src/ui/widgets/tooltip.rs index 73314f361a..9402991dfe 100644 --- a/voxygen/src/ui/widgets/tooltip.rs +++ b/voxygen/src/ui/widgets/tooltip.rs @@ -99,6 +99,7 @@ impl TooltipManager { img_id: Option, image_dims: Option<(f64, f64)>, src_id: widget::Id, + bottom_offset: f64, ui: &mut UiCell, ) { let tooltip_id = self.tooltip_id; @@ -115,13 +116,13 @@ impl TooltipManager { .image_dims(image_dims); let [t_w, t_h] = tooltip.get_wh(ui).unwrap_or([0.0, 0.0]); - let [m_x, m_y] = mouse_pos; + let [m_x, m_y] = [mouse_pos[0], mouse_pos[1]]; let (w_w, w_h) = (ui.win_w, ui.win_h); // Determine position based on size and mouse position // Flow to the bottom right of the mouse let x = (m_x + t_w / 2.0).min(w_w / 2.0 - t_w / 2.0); - let y = (m_y - mp_h - t_h / 2.0).max(-w_h / 2.0 + t_h / 2.0); + let y = (m_y - mp_h - t_h / 2.0).max(-w_h / 2.0 + t_h / 2.0 + bottom_offset); tooltip .floating(true) .transparency(transparency) @@ -154,6 +155,8 @@ pub struct Tooltipped<'a, W> { desc_text: &'a str, img_id: Option, image_dims: Option<(f64, f64)>, + // Offsets limit of bottom of tooltip + bottom_offset: Option, tooltip: &'a Tooltip<'a>, } impl<'a, W: Widget> Tooltipped<'a, W> { @@ -167,6 +170,11 @@ impl<'a, W: Widget> Tooltipped<'a, W> { self } + pub fn bottom_offset(mut self, off: f64) -> Self { + self.bottom_offset = Some(off); + self + } + pub fn set(self, id: widget::Id, ui: &mut UiCell) -> W::Event { let event = self.inner.set(id, ui); self.tooltip_manager.set_tooltip( @@ -176,6 +184,7 @@ impl<'a, W: Widget> Tooltipped<'a, W> { self.img_id, self.image_dims, id, + self.bottom_offset.unwrap_or(0.0), ui, ); event @@ -209,6 +218,7 @@ impl Tooltipable for W { desc_text, img_id: None, image_dims: None, + bottom_offset: None, tooltip, } }