Use new slot widget for armor slots

This commit is contained in:
Imbris 2020-04-04 13:51:41 -04:00 committed by Pfauenauge90
parent 968c064874
commit 0b932ae99a
5 changed files with 226 additions and 204 deletions

View File

@ -387,6 +387,8 @@ impl Client {
pub fn inventories(&self) -> ReadStorage<comp::Inventory> { self.state.read_storage() }
pub fn loadouts(&self) -> ReadStorage<comp::Loadout> { self.state.read_storage() }
/// Send a chat message to the server.
pub fn send_chat(&mut self, message: String) {
match validate_chat_msg(&message) {

View File

@ -7,6 +7,15 @@ use vek::*;
/// Default duration before an input is considered 'held'.
pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum InventoryManip {
Pickup(Uid),
Collect(Vec3<i32>),
Use(usize),
Swap(usize, usize),
Drop(usize),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ControlEvent {
Mount(Uid),
@ -230,12 +239,3 @@ pub struct Mounting(pub Uid);
impl Component for Mounting {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum InventoryManip {
Pickup(Uid),
Collect(Vec3<i32>),
Use(usize),
Swap(usize, usize),
Drop(usize),
}

View File

@ -1,7 +1,7 @@
use super::{
img_ids::{Imgs, ImgsRot},
item_imgs::ItemImgs,
slot_kinds::{HudSlotManager, InventorySlot},
slot_kinds::{ArmorSlot, HudSlotManager, InventorySlot},
Event as HudEvent, Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
XP_COLOR,
};
@ -47,7 +47,7 @@ widget_ids! {
tab_2,
tab_3,
tab_4,
//Stats
// Stats
stats_alignment,
level,
exp_rectangle,
@ -57,36 +57,23 @@ widget_ids! {
divider,
statnames,
stats,
//Armor Slots
// Armor Slots
slots_bg,
head_bg,
neck_bg,
chest_bg,
shoulder_bg,
hands_bg,
legs_bg,
belt_bg,
ring_r_bg,
ring_l_bg,
foot_bg,
back_bg,
tabard_bg,
mainhand_bg,
offhand_bg,
head_ico,
neck_ico,
chest_ico,
shoulder_ico,
hands_ico,
legs_ico,
belt_ico,
ring_r_ico,
ring_l_ico,
foot_ico,
back_ico,
tabard_ico,
mainhand_ico,
offhand_ico,
head_slot,
neck_slot,
chest_slot,
shoulders_slot,
hands_slot,
legs_slot,
belt_slot,
ring_r_slot,
ring_l_slot,
feet_slot,
back_slot,
tabard_slot,
mainhand_slot,
offhand_slot,
// ???
end_ico,
fit_ico,
wp_ico,
@ -143,7 +130,6 @@ impl<'a> Bag<'a> {
pub struct State {
ids: Ids,
selected_slot: Option<usize>,
}
pub enum Event {
@ -160,7 +146,6 @@ impl<'a> Widget for Bag<'a> {
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
ids: Ids::new(id_gen),
selected_slot: None,
}
}
@ -173,9 +158,15 @@ impl<'a> Widget for Bag<'a> {
let invs = self.client.inventories();
let inventory = match invs.get(self.client.entity()) {
Some(inv) => inv,
Some(i) => i,
None => return None,
};
let loadouts = self.client.loadouts();
let loadout = match loadouts.get(self.client.entity()) {
Some(l) => l,
None => return None,
};
let exp_percentage = (self.stats.exp.current() as f64) / (self.stats.exp.maximum() as f64);
let exp_treshold = format!(
"{}/{} {}",
@ -322,174 +313,173 @@ impl<'a> Widget for Bag<'a> {
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.slots_bg, ui);*/
// Armor Slots
//Head
Image::new(self.imgs.armor_slot)
let mut slot_maker = SlotMaker {
background: self.imgs.armor_slot,
selected_background: self.imgs.armor_slot,
background_color: Some(UI_HIGHLIGHT_0),
content_size: Vec2::broadcast(30.0),
selected_content_size: Vec2::broadcast(32.0),
amount_font: self.fonts.cyri.conrod_id,
amount_margins: Vec2::new(-4.0, 0.0),
amount_font_size: self.fonts.cyri.scale(12),
amount_text_color: TEXT_COLOR,
content_source: loadout,
image_source: self.item_imgs,
slot_manager: Some(self.slot_manager),
};
// Head
let (title, desc) = ("Helmet", "");
slot_maker
.fabricate(ArmorSlot::Head)
.w_h(45.0, 45.0)
.mid_top_with_margin_on(state.ids.bg_frame, 60.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.head_bg, ui);
Button::image(self.imgs.head_bg)
.w_h(32.0, 40.0)
.image_color(UI_MAIN)
.middle_of(state.ids.head_bg)
.with_tooltip(self.tooltip_manager, "Helmet", "", &item_tooltip)
.set(state.ids.head_ico, ui);
//Necklace
Image::new(self.imgs.armor_slot)
.with_icon(self.imgs.head_bg, Vec2::new(32.0, 40.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.head_slot, ui);
// Necklace
let (title, desc) = ("Neck", "");
slot_maker
.fabricate(ArmorSlot::Neck)
.w_h(45.0, 45.0)
.mid_bottom_with_margin_on(state.ids.head_bg, -55.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.neck_bg, ui);
Button::image(self.imgs.necklace_bg)
.w_h(40.0, 31.0)
.image_color(UI_MAIN)
.middle_of(state.ids.neck_bg)
.with_tooltip(self.tooltip_manager, "Neck", "", &item_tooltip)
.set(state.ids.neck_ico, ui);
//Chest
Image::new(self.imgs.armor_slot) // different graphics for empty/non empty
.mid_bottom_with_margin_on(state.ids.head_slot, -55.0)
.with_icon(self.imgs.necklace_bg, Vec2::new(40.0, 31.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.neck_slot, ui);
// Chest
//Image::new(self.imgs.armor_slot) // different graphics for empty/non empty
let (title, desc) = loadout
.chest
.as_ref()
.map_or(("Chest", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Chest)
.w_h(85.0, 85.0)
.mid_bottom_with_margin_on(state.ids.neck_bg, -95.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.chest_bg, ui);
Button::image(self.imgs.chest_bg)
.w_h(64.0, 42.0)
.image_color(UI_MAIN)
.middle_of(state.ids.chest_bg)
.with_tooltip(self.tooltip_manager, "Chest", "", &item_tooltip)
.set(state.ids.chest_ico, ui);
//Shoulder
Image::new(self.imgs.armor_slot)
.mid_bottom_with_margin_on(state.ids.neck_slot, -95.0)
.with_icon(self.imgs.chest_bg, Vec2::new(64.0, 42.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.chest_slot, ui);
// Shoulders
let (title, desc) = loadout
.shoulder
.as_ref()
.map_or(("Shoulders", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Shoulders)
.w_h(70.0, 70.0)
.bottom_left_with_margins_on(state.ids.chest_bg, 0.0, -80.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.shoulder_bg, ui);
Button::image(self.imgs.shoulders_bg)
.w_h(60.0, 36.0)
.image_color(UI_MAIN)
.middle_of(state.ids.shoulder_bg)
.with_tooltip(self.tooltip_manager, "Shoulders", "", &item_tooltip)
.set(state.ids.shoulder_ico, ui);
//Hands
Image::new(self.imgs.armor_slot)
.bottom_left_with_margins_on(state.ids.chest_slot, 0.0, -80.0)
.with_icon(self.imgs.shoulders_bg, Vec2::new(60.0, 36.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.shoulders_slot, ui);
// Hands
let (title, desc) = loadout
.hand
.as_ref()
.map_or(("Hands", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Hands)
.w_h(70.0, 70.0)
.bottom_right_with_margins_on(state.ids.chest_bg, 0.0, -80.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.hands_bg, ui);
Button::image(self.imgs.hands_bg)
.w_h(55.0, 60.0)
.image_color(UI_MAIN)
.middle_of(state.ids.hands_bg)
.with_tooltip(self.tooltip_manager, "Hands", "", &item_tooltip)
.set(state.ids.hands_ico, ui);
//Belt
Image::new(self.imgs.armor_slot)
.bottom_right_with_margins_on(state.ids.chest_slot, 0.0, -80.0)
.with_icon(self.imgs.hands_bg, Vec2::new(55.0, 60.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.hands_slot, ui);
// Belt
let (title, desc) = loadout
.belt
.as_ref()
.map_or(("Belt", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Belt)
.w_h(45.0, 45.0)
.mid_bottom_with_margin_on(state.ids.chest_bg, -55.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.belt_bg, ui);
Button::image(self.imgs.belt_bg)
.w_h(40.0, 23.0)
.image_color(UI_MAIN)
.middle_of(state.ids.belt_bg)
.with_tooltip(self.tooltip_manager, "Belt", "", &item_tooltip)
.set(state.ids.belt_ico, ui);
//Legs
Image::new(self.imgs.armor_slot)
.mid_bottom_with_margin_on(state.ids.chest_slot, -55.0)
.with_icon(self.imgs.belt_bg, Vec2::new(40.0, 23.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.belt_slot, ui);
// Legs
let (title, desc) = loadout
.belt
.as_ref()
.map_or(("Legs", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Legs)
.w_h(85.0, 85.0)
.mid_bottom_with_margin_on(state.ids.belt_bg, -95.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.legs_bg, ui);
Button::image(self.imgs.legs_bg)
.w_h(48.0, 70.0)
.image_color(UI_MAIN)
.middle_of(state.ids.legs_bg)
.with_tooltip(self.tooltip_manager, "Legs", "", &item_tooltip)
.set(state.ids.legs_ico, ui);
//Ring-L
Image::new(self.imgs.armor_slot)
.mid_bottom_with_margin_on(state.ids.belt_slot, -95.0)
.with_icon(self.imgs.legs_bg, Vec2::new(48.0, 70.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.legs_slot, ui);
// Ring-L
let (title, desc) = ("Left Ring", "");
slot_maker
.fabricate(ArmorSlot::LeftRing)
.w_h(45.0, 45.0)
.bottom_right_with_margins_on(state.ids.shoulder_bg, -55.0, 0.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.ring_l_bg, ui);
Button::image(self.imgs.ring_l_bg)
.w_h(36.0, 40.0)
.image_color(UI_MAIN)
.middle_of(state.ids.ring_l_bg)
.with_tooltip(self.tooltip_manager, "Left Ring", "", &item_tooltip)
.set(state.ids.ring_l_ico, ui);
//Ring-R
Image::new(self.imgs.armor_slot)
.bottom_right_with_margins_on(state.ids.shoulders_slot, -55.0, 0.0)
.with_icon(self.imgs.ring_l_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.ring_l_slot, ui);
// Ring-R
let (title, desc) = ("Right Ring", "");
slot_maker
.fabricate(ArmorSlot::RightRing)
.w_h(45.0, 45.0)
.bottom_left_with_margins_on(state.ids.hands_bg, -55.0, 0.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.ring_r_bg, ui);
Button::image(self.imgs.ring_r_bg)
.w_h(36.0, 40.0)
.image_color(UI_MAIN)
.middle_of(state.ids.ring_r_bg)
.with_tooltip(self.tooltip_manager, "Right Ring", "", &item_tooltip)
.set(state.ids.ring_r_ico, ui);
//Back
Image::new(self.imgs.armor_slot)
.bottom_left_with_margins_on(state.ids.hands_slot, -55.0, 0.0)
.with_icon(self.imgs.ring_r_bg, Vec2::new(36.0, 40.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.ring_r_slot, ui);
// Back
let (title, desc) = ("Back", "");
slot_maker
.fabricate(ArmorSlot::Back)
.w_h(45.0, 45.0)
.down_from(state.ids.ring_l_bg, 10.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.back_bg, ui);
Button::image(self.imgs.back_bg)
.w_h(33.0, 40.0)
.image_color(UI_MAIN)
.middle_of(state.ids.back_bg)
.with_tooltip(self.tooltip_manager, "Back", "", &item_tooltip)
.set(state.ids.back_ico, ui);
//Foot
Image::new(self.imgs.armor_slot)
.down_from(state.ids.ring_l_slot, 10.0)
.with_icon(self.imgs.back_bg, Vec2::new(33.0, 40.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.back_slot, ui);
// Foot
let (title, desc) = loadout
.foot
.as_ref()
.map_or(("Feet", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Feet)
.w_h(45.0, 45.0)
.down_from(state.ids.ring_r_bg, 10.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.foot_bg, ui);
Button::image(self.imgs.feet_bg)
.w_h(32.0, 40.0)
.image_color(UI_MAIN)
.middle_of(state.ids.foot_bg)
.with_tooltip(self.tooltip_manager, "Feet", "", &item_tooltip)
.set(state.ids.foot_ico, ui);
//Tabard
Image::new(self.imgs.armor_slot)
.down_from(state.ids.ring_r_slot, 10.0)
.with_icon(self.imgs.feet_bg, Vec2::new(32.0, 40.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.feet_slot, ui);
// Tabard
let (title, desc) = ("Tabard", "");
slot_maker
.fabricate(ArmorSlot::Tabard)
.w_h(70.0, 70.0)
.top_right_with_margins_on(state.ids.bg_frame, 80.5, 53.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.tabard_bg, ui);
Button::image(self.imgs.tabard_bg)
.w_h(60.0, 60.0)
.image_color(UI_MAIN)
.middle_of(state.ids.tabard_bg)
.with_tooltip(self.tooltip_manager, "Tabard", "", &item_tooltip)
.set(state.ids.tabard_ico, ui);
//Mainhand/Left-Slot
Image::new(self.imgs.armor_slot)
.with_icon(self.imgs.tabard_bg, Vec2::new(60.0, 60.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.tabard_slot, ui);
// Mainhand/Left-Slot
let (title, desc) = loadout
.active_item
.as_ref()
.map(|i| &i.item)
.map_or(("Mainhand", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Mainhand)
.w_h(85.0, 85.0)
.bottom_right_with_margins_on(state.ids.back_bg, -95.0, 0.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.mainhand_bg, ui);
Button::image(self.imgs.mainhand_bg)
.w_h(75.0, 75.0)
.image_color(UI_MAIN)
.middle_of(state.ids.mainhand_bg)
.with_tooltip(self.tooltip_manager, "Mainhand", "", &item_tooltip)
.set(state.ids.mainhand_ico, ui);
//Offhand/Right-Slot
Image::new(self.imgs.armor_slot)
.bottom_right_with_margins_on(state.ids.back_slot, -95.0, 0.0)
.with_icon(self.imgs.mainhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.mainhand_slot, ui);
// Offhand/Right-Slot
let (title, desc) = loadout
.second_item
.as_ref()
.map(|i| &i.item)
.map_or(("Offhand", ""), |item| (item.name(), item.description()));
slot_maker
.fabricate(ArmorSlot::Offhand)
.w_h(85.0, 85.0)
.bottom_left_with_margins_on(state.ids.foot_bg, -95.0, 0.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.offhand_bg, ui);
Button::image(self.imgs.offhand_bg)
.w_h(75.0, 75.0)
.image_color(UI_MAIN)
.middle_of(state.ids.offhand_bg)
.with_tooltip(self.tooltip_manager, "Offhand", "", &item_tooltip)
.set(state.ids.offhand_ico, ui);
.bottom_left_with_margins_on(state.ids.feet_slot, -95.0, 0.0)
.with_icon(self.imgs.offhand_bg, Vec2::new(75.0, 75.0), Some(UI_MAIN))
.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip)
.set(state.ids.offhand_slot, ui);
} else {
// Stats
// Title

View File

@ -1,8 +1,7 @@
use super::item_imgs::{ItemImgs, ItemKey};
use crate::ui::slot::{ContentKey, SlotKinds, SlotManager};
use common::comp::{item::ItemKind, Inventory};
use common::comp::{item::ItemKind, Inventory, Loadout};
use conrod_core::image;
use vek::*;
#[derive(Clone, Copy, PartialEq)]
pub enum HudSlotKinds {
@ -18,7 +17,7 @@ pub struct InventorySlot(pub usize);
#[derive(Clone, Copy, PartialEq)]
pub enum ArmorSlot {
Helmet,
Head,
Neck,
Shoulders,
Chest,
@ -72,8 +71,32 @@ impl ContentKey for InventorySlot {
fn image_id(key: &Self::ImageKey, source: &Self::ImageSource) -> image::Id {
source.img_id_or_not_found_img(key.clone())
}
}
fn back_icon(&self, _: &Self::ImageSource) -> Option<(image::Id, Vec2<f32>)> { None }
impl ContentKey for ArmorSlot {
type ContentSource = Loadout;
type ImageKey = ItemKey;
type ImageSource = ItemImgs;
fn image_key(&self, source: &Self::ContentSource) -> Option<Self::ImageKey> {
let item = match self {
ArmorSlot::Shoulders => source.shoulder.as_ref(),
ArmorSlot::Chest => source.chest.as_ref(),
ArmorSlot::Belt => source.belt.as_ref(),
ArmorSlot::Hands => source.hand.as_ref(),
ArmorSlot::Legs => source.pants.as_ref(),
ArmorSlot::Feet => source.foot.as_ref(),
_ => None,
};
item.map(Into::into)
}
fn amount(&self, _: &Self::ContentSource) -> Option<u32> { None }
fn image_id(key: &Self::ImageKey, source: &Self::ImageSource) -> image::Id {
source.img_id_or_not_found_img(key.clone())
}
}
impl From<InventorySlot> for HudSlotKinds {

View File

@ -18,8 +18,6 @@ pub trait ContentKey: Copy {
// TODO: is this the right integer type?
fn amount(&self, source: &Self::ContentSource) -> Option<u32>;
fn image_id(key: &Self::ImageKey, source: &Self::ImageSource) -> image::Id;
/// Returns slot icon and icon size as fraction of slot size
fn back_icon(&self, source: &Self::ImageSource) -> Option<(image::Id, Vec2<f32>)>;
}
pub trait SlotKinds: Sized + PartialEq + Copy {}
@ -223,6 +221,8 @@ pub struct Slot<'a, C: ContentKey + Into<K>, K: SlotKinds> {
// TODO: maybe use constant scale factor or move this setting to the slot manager?
selected_content_size: Vec2<f32>,
icon: Option<(image::Id, Vec2<f32>, Option<Color>)>,
// Amount styling
amount_font: font::Id,
amount_font_size: u32,
@ -265,6 +265,11 @@ where
pub with_background_color { background_color = Some(Color) }
}
pub fn with_icon(mut self, img: image::Id, size: Vec2<f32>, color: Option<Color>) -> Self {
self.icon = Some((img, size, color));
self
}
fn new(
content: C,
background: image::Id,
@ -285,6 +290,7 @@ where
background_color: None,
content_size,
selected_content_size,
icon: None,
amount_font,
amount_font_size,
amount_margins,
@ -331,6 +337,7 @@ where
background_color,
content_size,
selected_content_size,
icon,
amount_font,
amount_font_size,
amount_margins,
@ -362,7 +369,6 @@ where
} else {
background
};
let icon = content.back_icon(image_source);
let content_image = state.cached_image.as_ref().map(|c| c.1);
// Get amount (None => no amount text)
@ -381,13 +387,14 @@ where
.set(state.ids.background, ui);
// Draw icon
if let Some((icon_image, size_frac)) = icon {
let wh = (size_frac.map(|e| e as f64) * Vec2::new(w, h)).into_array();
if let Some((icon_image, size, color)) = icon {
let wh = size.map(|e| e as f64).into_array();
Image::new(icon_image)
.x_y(x, y)
.wh(wh)
.parent(id)
.graphics_for(id)
.color(color)
.set(state.ids.icon, ui);
}