2021-08-05 20:08:56 +00:00
|
|
|
use conrod_core::{
|
|
|
|
color,
|
|
|
|
position::Relative,
|
2022-03-06 06:18:25 +00:00
|
|
|
widget::{self, Button, Image, Rectangle, State as ConrodState, Text, TextEdit},
|
2021-08-05 20:08:56 +00:00
|
|
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
|
2021-02-10 04:44:49 +00:00
|
|
|
};
|
2021-08-05 20:08:56 +00:00
|
|
|
use specs::Entity as EcsEntity;
|
|
|
|
use vek::*;
|
|
|
|
|
2021-02-10 04:44:49 +00:00
|
|
|
use client::Client;
|
2021-02-12 10:51:32 +00:00
|
|
|
use common::{
|
2021-02-25 19:04:09 +00:00
|
|
|
comp::{
|
2024-01-16 16:40:12 +00:00
|
|
|
inventory::item::{ItemDesc, ItemI18n, MaterialStatManifest, Quality},
|
2022-03-06 06:18:25 +00:00
|
|
|
Inventory, Stats,
|
2021-02-25 19:04:09 +00:00
|
|
|
},
|
2022-03-06 22:39:01 +00:00
|
|
|
trade::{PendingTrade, SitePrices, TradeAction, TradePhase},
|
2021-02-12 10:51:32 +00:00
|
|
|
};
|
2021-02-12 02:53:25 +00:00
|
|
|
use common_net::sync::WorldSyncExt;
|
2021-07-29 18:47:45 +00:00
|
|
|
use i18n::Localization;
|
2021-08-05 20:08:56 +00:00
|
|
|
|
|
|
|
use crate::{
|
2023-06-26 14:39:30 +00:00
|
|
|
hud::{
|
|
|
|
bag::{BackgroundIds, InventoryScroller},
|
|
|
|
Event as HudEvent, PromptDialogSettings,
|
|
|
|
},
|
2021-08-05 20:08:56 +00:00
|
|
|
ui::{
|
|
|
|
fonts::Fonts,
|
|
|
|
slot::{ContentSize, SlotMaker},
|
2023-01-12 23:26:50 +00:00
|
|
|
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
|
|
|
|
Tooltipable,
|
2021-08-05 20:08:56 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
use super::{
|
|
|
|
img_ids::{Imgs, ImgsRot},
|
|
|
|
item_imgs::ItemImgs,
|
2022-03-06 06:18:25 +00:00
|
|
|
slots::{SlotKind, SlotManager, TradeSlot},
|
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, Hud, HudInfo, Show, TradeAmountInput, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0,
|
|
|
|
UI_MAIN,
|
2021-08-05 20:08:56 +00:00
|
|
|
};
|
2021-07-31 23:37:45 +00:00
|
|
|
use std::borrow::Cow;
|
2021-02-10 04:44:49 +00:00
|
|
|
|
2023-01-12 23:26:50 +00:00
|
|
|
pub enum TradeEvent {
|
|
|
|
TradeAction(TradeAction),
|
|
|
|
SetDetailsMode(bool),
|
|
|
|
HudUpdate(HudUpdate),
|
2023-06-26 14:39:30 +00:00
|
|
|
ShowPrompt(PromptDialogSettings),
|
2023-01-12 23:26:50 +00:00
|
|
|
}
|
|
|
|
|
2022-03-06 22:39:01 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum HudUpdate {
|
|
|
|
Focus(widget::Id),
|
2022-03-08 07:35:09 +00:00
|
|
|
Submit,
|
2022-03-06 22:39:01 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 04:44:49 +00:00
|
|
|
pub struct State {
|
|
|
|
ids: Ids,
|
2021-02-28 02:44:57 +00:00
|
|
|
bg_ids: BackgroundIds,
|
2021-02-10 04:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
widget_ids! {
|
|
|
|
pub struct Ids {
|
|
|
|
trade_close,
|
|
|
|
bg,
|
|
|
|
bg_frame,
|
|
|
|
trade_title_bg,
|
|
|
|
trade_title,
|
2021-02-12 02:53:25 +00:00
|
|
|
inv_alignment[],
|
|
|
|
inv_slots[],
|
2021-02-12 10:51:32 +00:00
|
|
|
inv_textslots[],
|
2021-02-12 02:53:25 +00:00
|
|
|
offer_headers[],
|
2021-02-12 10:51:32 +00:00
|
|
|
accept_indicators[],
|
2021-02-12 02:53:25 +00:00
|
|
|
phase_indicator,
|
2021-02-12 10:51:32 +00:00
|
|
|
accept_button,
|
|
|
|
decline_button,
|
2021-02-28 02:44:57 +00:00
|
|
|
inventory_scroller,
|
2022-03-06 06:18:25 +00:00
|
|
|
amount_bg,
|
|
|
|
amount_notice,
|
|
|
|
amount_open_label,
|
|
|
|
amount_open_btn,
|
|
|
|
amount_open_ovlay,
|
|
|
|
amount_input,
|
|
|
|
amount_btn,
|
2023-01-12 23:26:50 +00:00
|
|
|
trade_details_btn,
|
2021-02-10 04:44:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(WidgetCommon)]
|
|
|
|
pub struct Trade<'a> {
|
|
|
|
client: &'a Client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info: &'a HudInfo,
|
2021-02-10 04:44:49 +00:00
|
|
|
imgs: &'a Imgs,
|
|
|
|
item_imgs: &'a ItemImgs,
|
|
|
|
fonts: &'a Fonts,
|
2021-02-19 20:20:27 +00:00
|
|
|
rot_imgs: &'a ImgsRot,
|
2023-01-12 23:26:50 +00:00
|
|
|
tooltip_manager: &'a mut TooltipManager,
|
2021-03-16 12:19:31 +00:00
|
|
|
item_tooltip_manager: &'a mut ItemTooltipManager,
|
2021-02-10 04:44:49 +00:00
|
|
|
#[conrod(common_builder)]
|
|
|
|
common: widget::CommonBuilder,
|
|
|
|
slot_manager: &'a mut SlotManager,
|
|
|
|
localized_strings: &'a Localization,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n: &'a ItemI18n,
|
2021-02-25 19:04:09 +00:00
|
|
|
msm: &'a MaterialStatManifest,
|
2021-02-16 01:05:54 +00:00
|
|
|
pulse: f32,
|
2022-03-06 06:18:25 +00:00
|
|
|
show: &'a mut Show,
|
2023-06-26 14:39:30 +00:00
|
|
|
needs_thirdconfirm: bool,
|
2021-02-10 04:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Trade<'a> {
|
|
|
|
pub fn new(
|
|
|
|
client: &'a Client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info: &'a HudInfo,
|
2021-02-10 04:44:49 +00:00
|
|
|
imgs: &'a Imgs,
|
|
|
|
item_imgs: &'a ItemImgs,
|
|
|
|
fonts: &'a Fonts,
|
2021-02-19 20:20:27 +00:00
|
|
|
rot_imgs: &'a ImgsRot,
|
2023-01-12 23:26:50 +00:00
|
|
|
tooltip_manager: &'a mut TooltipManager,
|
2021-03-16 12:19:31 +00:00
|
|
|
item_tooltip_manager: &'a mut ItemTooltipManager,
|
2021-02-10 04:44:49 +00:00
|
|
|
slot_manager: &'a mut SlotManager,
|
|
|
|
localized_strings: &'a Localization,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n: &'a ItemI18n,
|
2021-02-25 19:04:09 +00:00
|
|
|
msm: &'a MaterialStatManifest,
|
2021-02-16 01:05:54 +00:00
|
|
|
pulse: f32,
|
2022-03-06 06:18:25 +00:00
|
|
|
show: &'a mut Show,
|
2021-02-10 04:44:49 +00:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
client,
|
2022-07-06 09:20:18 +00:00
|
|
|
info,
|
2021-02-10 04:44:49 +00:00
|
|
|
imgs,
|
|
|
|
item_imgs,
|
|
|
|
fonts,
|
2021-02-19 20:20:27 +00:00
|
|
|
rot_imgs,
|
2023-01-12 23:26:50 +00:00
|
|
|
tooltip_manager,
|
2021-03-16 12:19:31 +00:00
|
|
|
item_tooltip_manager,
|
2021-02-10 04:44:49 +00:00
|
|
|
common: widget::CommonBuilder::default(),
|
|
|
|
slot_manager,
|
|
|
|
localized_strings,
|
2024-01-16 16:40:12 +00:00
|
|
|
item_i18n,
|
2021-02-25 19:04:09 +00:00
|
|
|
msm,
|
2021-02-16 01:05:54 +00:00
|
|
|
pulse,
|
2022-03-06 06:18:25 +00:00
|
|
|
show,
|
2023-06-26 14:39:30 +00:00
|
|
|
needs_thirdconfirm: false,
|
2021-02-10 04:44:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-05 20:08:56 +00:00
|
|
|
|
2021-02-12 10:51:32 +00:00
|
|
|
const MAX_TRADE_SLOTS: usize = 16;
|
2021-02-10 04:44:49 +00:00
|
|
|
|
2021-02-12 02:53:25 +00:00
|
|
|
impl<'a> Trade<'a> {
|
|
|
|
fn background(&mut self, state: &mut ConrodState<'_, State>, ui: &mut UiCell<'_>) {
|
2021-08-05 20:08:56 +00:00
|
|
|
Image::new(self.imgs.inv_middle_bg_bag)
|
2021-08-08 11:45:26 +00:00
|
|
|
.w_h(424.0, 482.0)
|
2021-02-12 02:53:25 +00:00
|
|
|
.color(Some(UI_MAIN))
|
2021-08-08 11:45:26 +00:00
|
|
|
.mid_bottom_with_margin_on(ui.window, 295.0)
|
2021-02-12 02:53:25 +00:00
|
|
|
.set(state.ids.bg, ui);
|
2021-08-05 20:08:56 +00:00
|
|
|
Image::new(self.imgs.inv_middle_frame)
|
2021-08-08 11:45:26 +00:00
|
|
|
.w_h(424.0, 482.0)
|
2021-02-12 02:53:25 +00:00
|
|
|
.middle_of(state.ids.bg)
|
|
|
|
.color(Some(UI_HIGHLIGHT_0))
|
|
|
|
.set(state.ids.bg_frame, ui);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn title(&mut self, state: &mut ConrodState<'_, State>, ui: &mut UiCell<'_>) {
|
2022-08-23 11:14:29 +00:00
|
|
|
Text::new(&self.localized_strings.get_msg("hud-trade-trade_window"))
|
2021-02-12 02:53:25 +00:00
|
|
|
.mid_top_with_margin_on(state.ids.bg_frame, 9.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
|
|
|
|
.set(state.ids.trade_title_bg, ui);
|
2022-08-23 11:14:29 +00:00
|
|
|
Text::new(&self.localized_strings.get_msg("hud-trade-trade_window"))
|
2021-02-12 02:53:25 +00:00
|
|
|
.top_left_with_margins_on(state.ids.trade_title_bg, 2.0, 2.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.set(state.ids.trade_title, ui);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn phase_indicator(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
|
|
|
trade: &'a PendingTrade,
|
|
|
|
) {
|
2021-02-13 23:32:55 +00:00
|
|
|
let phase_text = match trade.phase() {
|
2022-08-23 17:18:18 +00:00
|
|
|
TradePhase::Mutate => self
|
|
|
|
.localized_strings
|
|
|
|
.get_msg("hud-trade-phase1_description"),
|
|
|
|
TradePhase::Review => self
|
|
|
|
.localized_strings
|
|
|
|
.get_msg("hud-trade-phase2_description"),
|
|
|
|
TradePhase::Complete => self
|
|
|
|
.localized_strings
|
|
|
|
.get_msg("hud-trade-phase3_description"),
|
2021-02-12 02:53:25 +00:00
|
|
|
};
|
|
|
|
|
2022-08-06 17:47:45 +00:00
|
|
|
Text::new(&phase_text)
|
2021-02-12 02:53:25 +00:00
|
|
|
.mid_top_with_margin_on(state.ids.bg, 70.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
|
|
|
.set(state.ids.phase_indicator, ui);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn item_pane(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
|
|
|
trade: &'a PendingTrade,
|
2021-03-25 04:35:33 +00:00
|
|
|
prices: &'a Option<SitePrices>,
|
2021-03-15 01:41:47 +00:00
|
|
|
ours: bool,
|
2023-01-12 23:26:50 +00:00
|
|
|
) -> Option<TradeEvent> {
|
|
|
|
let mut event = None;
|
2021-02-12 02:53:25 +00:00
|
|
|
let inventories = self.client.inventories();
|
2021-03-15 01:41:47 +00:00
|
|
|
let check_if_us = |who: usize| -> Option<_> {
|
|
|
|
let uid = trade.parties[who];
|
2023-04-23 05:58:29 +00:00
|
|
|
let entity = self.client.state().ecs().entity_from_uid(uid)?;
|
2021-03-15 01:41:47 +00:00
|
|
|
let is_ours = entity == self.client.entity();
|
|
|
|
Some(((who, uid, entity), is_ours))
|
|
|
|
};
|
|
|
|
let (who, uid, entity) = match check_if_us(0)? {
|
|
|
|
(x, is_ours) if ours == is_ours => x,
|
|
|
|
_ => check_if_us(1)?.0,
|
|
|
|
};
|
2021-07-11 18:27:34 +00:00
|
|
|
// TODO: update in accordance with https://gitlab.com/veloren/veloren/-/issues/960
|
2021-02-12 02:53:25 +00:00
|
|
|
let inventory = inventories.get(entity)?;
|
|
|
|
|
2021-02-12 10:51:32 +00:00
|
|
|
// Alignment for Grid
|
2021-08-05 20:08:56 +00:00
|
|
|
let mut alignment = Rectangle::fill_with([200.0, 180.0], color::TRANSPARENT);
|
2021-03-15 01:41:47 +00:00
|
|
|
if !ours {
|
2021-08-05 20:08:56 +00:00
|
|
|
alignment = alignment.top_left_with_margins_on(state.ids.bg, 180.0, 32.5);
|
2021-02-12 10:51:32 +00:00
|
|
|
} else {
|
2021-03-15 01:41:47 +00:00
|
|
|
alignment = alignment.right_from(state.ids.inv_alignment[1 - who], 0.0);
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
|
|
|
alignment
|
|
|
|
.scroll_kids_vertically()
|
|
|
|
.set(state.ids.inv_alignment[who], ui);
|
|
|
|
|
|
|
|
let name = self
|
|
|
|
.client
|
|
|
|
.player_list()
|
|
|
|
.get(&uid)
|
|
|
|
.map(|info| info.player_alias.clone())
|
2021-07-11 18:27:34 +00:00
|
|
|
.or_else(|| {
|
|
|
|
self.client
|
|
|
|
.state()
|
|
|
|
.read_storage::<Stats>()
|
|
|
|
.get(entity)
|
|
|
|
.map(|e| e.name.to_owned())
|
|
|
|
})
|
2021-02-12 10:51:32 +00:00
|
|
|
.unwrap_or_else(|| format!("Player {}", who));
|
|
|
|
|
2021-08-12 18:56:38 +00:00
|
|
|
let offer_header = if ours {
|
2022-09-08 19:51:02 +00:00
|
|
|
self.localized_strings.get_msg("hud-trade-your_offer")
|
2021-08-12 00:23:31 +00:00
|
|
|
} else {
|
2022-09-08 19:51:02 +00:00
|
|
|
self.localized_strings.get_msg("hud-trade-their_offer")
|
2021-08-12 00:23:31 +00:00
|
|
|
};
|
2021-08-05 20:08:56 +00:00
|
|
|
|
2021-02-12 10:51:32 +00:00
|
|
|
Text::new(&offer_header)
|
|
|
|
.up_from(state.ids.inv_alignment[who], 20.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
|
|
|
|
.set(state.ids.offer_headers[who], ui);
|
|
|
|
|
2021-02-13 23:32:55 +00:00
|
|
|
let has_accepted = trade.accept_flags[who];
|
2022-08-06 17:47:45 +00:00
|
|
|
let accept_indicator =
|
|
|
|
self.localized_strings
|
|
|
|
.get_msg_ctx("hud-trade-has_accepted", &i18n::fluent_args! {
|
|
|
|
"playername" => &name,
|
|
|
|
});
|
2021-02-12 10:51:32 +00:00
|
|
|
Text::new(&accept_indicator)
|
2021-08-05 20:08:56 +00:00
|
|
|
.down_from(state.ids.inv_alignment[who], 50.0)
|
2021-02-12 10:51:32 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
2021-02-12 23:09:18 +00:00
|
|
|
.color(Color::Rgba(
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
if has_accepted { 1.0 } else { 0.0 },
|
|
|
|
))
|
2021-02-12 10:51:32 +00:00
|
|
|
.set(state.ids.accept_indicators[who], ui);
|
|
|
|
|
2021-02-12 23:09:18 +00:00
|
|
|
let mut invslots: Vec<_> = trade.offers[who].iter().map(|(k, v)| (*k, *v)).collect();
|
2021-02-12 10:51:32 +00:00
|
|
|
invslots.sort();
|
|
|
|
let tradeslots: Vec<_> = invslots
|
|
|
|
.into_iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(index, (k, quantity))| TradeSlot {
|
|
|
|
index,
|
|
|
|
quantity,
|
|
|
|
invslot: Some(k),
|
2021-02-28 02:44:57 +00:00
|
|
|
ours,
|
|
|
|
entity,
|
2021-02-12 10:51:32 +00:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2021-02-13 23:32:55 +00:00
|
|
|
if matches!(trade.phase(), TradePhase::Mutate) {
|
2023-01-12 23:26:50 +00:00
|
|
|
event = self
|
|
|
|
.phase1_itemwidget(
|
|
|
|
state,
|
|
|
|
ui,
|
|
|
|
inventory,
|
|
|
|
who,
|
|
|
|
ours,
|
|
|
|
entity,
|
|
|
|
name,
|
|
|
|
prices,
|
|
|
|
&tradeslots,
|
|
|
|
)
|
|
|
|
.or(event);
|
2021-02-12 10:51:32 +00:00
|
|
|
} else {
|
2021-02-28 02:44:57 +00:00
|
|
|
self.phase2_itemwidget(state, ui, inventory, who, ours, entity, &tradeslots);
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 23:26:50 +00:00
|
|
|
event
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn phase1_itemwidget(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
|
|
|
inventory: &Inventory,
|
|
|
|
who: usize,
|
2021-02-28 02:44:57 +00:00
|
|
|
ours: bool,
|
|
|
|
entity: EcsEntity,
|
|
|
|
name: String,
|
2021-03-25 04:35:33 +00:00
|
|
|
prices: &'a Option<SitePrices>,
|
2021-02-12 23:09:18 +00:00
|
|
|
tradeslots: &[TradeSlot],
|
2023-01-12 23:26:50 +00:00
|
|
|
) -> Option<TradeEvent> {
|
|
|
|
let mut event = None;
|
2021-03-16 12:19:31 +00:00
|
|
|
// Tooltips
|
2021-03-24 22:17:25 +00:00
|
|
|
let item_tooltip = ItemTooltip::new(
|
2021-03-16 12:19:31 +00:00
|
|
|
{
|
|
|
|
// 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-03-16 12:19:31 +00:00
|
|
|
self.imgs,
|
|
|
|
self.item_imgs,
|
|
|
|
self.pulse,
|
|
|
|
self.msm,
|
2021-03-24 01:05:14 +00:00
|
|
|
self.localized_strings,
|
2024-01-16 16:40:12 +00:00
|
|
|
self.item_i18n,
|
2021-03-16 12:19:31 +00:00
|
|
|
)
|
2021-03-23 01:40:54 +00:00
|
|
|
.title_font_size(self.fonts.cyri.scale(20))
|
2021-03-16 12:19:31 +00:00
|
|
|
.parent(ui.window)
|
|
|
|
.desc_font_size(self.fonts.cyri.scale(12))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.desc_text_color(TEXT_COLOR);
|
|
|
|
|
2021-02-28 02:44:57 +00:00
|
|
|
if !ours {
|
|
|
|
InventoryScroller::new(
|
2021-03-25 04:35:33 +00:00
|
|
|
self.client,
|
2021-02-28 02:44:57 +00:00
|
|
|
self.imgs,
|
|
|
|
self.item_imgs,
|
|
|
|
self.fonts,
|
2021-03-16 12:19:31 +00:00
|
|
|
self.item_tooltip_manager,
|
2021-02-28 02:44:57 +00:00
|
|
|
self.slot_manager,
|
|
|
|
self.pulse,
|
|
|
|
self.localized_strings,
|
2024-01-16 16:40:12 +00:00
|
|
|
self.item_i18n,
|
2021-02-28 02:44:57 +00:00
|
|
|
false,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
&item_tooltip,
|
|
|
|
name,
|
2021-03-30 22:37:38 +00:00
|
|
|
entity,
|
2021-02-28 02:44:57 +00:00
|
|
|
false,
|
2021-07-11 18:41:52 +00:00
|
|
|
inventory,
|
2021-02-28 02:44:57 +00:00
|
|
|
&state.bg_ids,
|
2021-10-08 01:02:48 +00:00
|
|
|
false,
|
2023-01-12 23:26:50 +00:00
|
|
|
self.show.trade_details,
|
2021-02-28 02:44:57 +00:00
|
|
|
)
|
|
|
|
.set(state.ids.inventory_scroller, ui);
|
2023-01-12 23:26:50 +00:00
|
|
|
|
|
|
|
let bag_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))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.desc_text_color(TEXT_COLOR);
|
|
|
|
|
|
|
|
let buttons_top = 53.0;
|
|
|
|
let (txt, btn, hover, press) = if self.show.trade_details {
|
|
|
|
(
|
|
|
|
"Grid mode",
|
|
|
|
self.imgs.grid_btn,
|
|
|
|
self.imgs.grid_btn_hover,
|
|
|
|
self.imgs.grid_btn_press,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
"List mode",
|
|
|
|
self.imgs.list_btn,
|
|
|
|
self.imgs.list_btn_hover,
|
|
|
|
self.imgs.list_btn_press,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
let details_btn = Button::image(btn)
|
|
|
|
.w_h(32.0, 17.0)
|
|
|
|
.hover_image(hover)
|
|
|
|
.press_image(press);
|
|
|
|
if details_btn
|
|
|
|
.mid_top_with_margin_on(state.bg_ids.bg_frame, buttons_top)
|
|
|
|
.with_tooltip(self.tooltip_manager, txt, "", &bag_tooltip, TEXT_COLOR)
|
|
|
|
.set(state.ids.trade_details_btn, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
|
|
|
event = Some(TradeEvent::SetDetailsMode(!self.show.trade_details));
|
|
|
|
}
|
2021-02-28 02:44:57 +00:00
|
|
|
}
|
|
|
|
|
2021-02-12 02:53:25 +00:00
|
|
|
let mut slot_maker = SlotMaker {
|
|
|
|
empty_slot: self.imgs.inv_slot,
|
|
|
|
filled_slot: self.imgs.inv_slot,
|
|
|
|
selected_slot: self.imgs.inv_slot_sel,
|
|
|
|
background_color: Some(UI_MAIN),
|
|
|
|
content_size: ContentSize {
|
|
|
|
width_height_ratio: 1.0,
|
|
|
|
max_fraction: 0.75,
|
|
|
|
},
|
|
|
|
selected_content_scale: 1.067,
|
|
|
|
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: inventory,
|
|
|
|
image_source: self.item_imgs,
|
|
|
|
slot_manager: Some(self.slot_manager),
|
2021-02-16 01:05:54 +00:00
|
|
|
pulse: self.pulse,
|
2021-02-12 02:53:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if state.ids.inv_slots.len() < 2 * MAX_TRADE_SLOTS {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.inv_slots
|
|
|
|
.resize(2 * MAX_TRADE_SLOTS, &mut ui.widget_id_generator());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for i in 0..MAX_TRADE_SLOTS {
|
|
|
|
let x = i % 4;
|
|
|
|
let y = i / 4;
|
|
|
|
|
2021-02-12 10:51:32 +00:00
|
|
|
let slot = tradeslots.get(i).cloned().unwrap_or(TradeSlot {
|
|
|
|
index: i,
|
|
|
|
quantity: 0,
|
|
|
|
invslot: None,
|
2021-02-28 02:44:57 +00:00
|
|
|
ours,
|
|
|
|
entity,
|
2021-02-12 10:51:32 +00:00
|
|
|
});
|
2021-02-12 02:53:25 +00:00
|
|
|
// Slot
|
2021-02-12 10:51:32 +00:00
|
|
|
let slot_widget = slot_maker
|
2021-02-12 23:09:18 +00:00
|
|
|
.fabricate(slot, [40.0; 2])
|
2021-02-12 02:53:25 +00:00
|
|
|
.top_left_with_margins_on(
|
|
|
|
state.ids.inv_alignment[who],
|
|
|
|
0.0 + y as f64 * (40.0),
|
|
|
|
0.0 + x as f64 * (40.0),
|
|
|
|
);
|
2021-02-19 20:20:27 +00:00
|
|
|
let slot_id = state.ids.inv_slots[i + who * MAX_TRADE_SLOTS];
|
|
|
|
if let Some(Some(item)) = slot.invslot.and_then(|slotid| inventory.slot(slotid)) {
|
|
|
|
let quality_col_img = match item.quality() {
|
|
|
|
Quality::Low => self.imgs.inv_slot_grey,
|
2021-11-04 17:50:14 +00:00
|
|
|
Quality::Common => self.imgs.inv_slot_common,
|
2021-02-19 20:20:27 +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,
|
|
|
|
};
|
2021-03-24 22:17:25 +00:00
|
|
|
|
2021-02-19 20:20:27 +00:00
|
|
|
slot_widget
|
|
|
|
.filled_slot(quality_col_img)
|
2021-10-14 02:54:59 +00:00
|
|
|
.with_item_tooltip(
|
|
|
|
self.item_tooltip_manager,
|
|
|
|
core::iter::once(item as &dyn ItemDesc),
|
|
|
|
prices,
|
|
|
|
&item_tooltip,
|
|
|
|
)
|
2021-02-19 20:20:27 +00:00
|
|
|
.set(slot_id, ui);
|
|
|
|
} else {
|
|
|
|
slot_widget.set(slot_id, ui);
|
|
|
|
}
|
2021-02-12 02:53:25 +00:00
|
|
|
}
|
2023-01-12 23:26:50 +00:00
|
|
|
event
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
2021-02-12 23:09:18 +00:00
|
|
|
|
2021-02-12 10:51:32 +00:00
|
|
|
fn phase2_itemwidget(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
|
|
|
inventory: &Inventory,
|
|
|
|
who: usize,
|
2021-02-28 02:44:57 +00:00
|
|
|
ours: bool,
|
|
|
|
entity: EcsEntity,
|
2021-02-12 23:09:18 +00:00
|
|
|
tradeslots: &[TradeSlot],
|
2021-02-12 10:51:32 +00:00
|
|
|
) {
|
|
|
|
if state.ids.inv_textslots.len() < 2 * MAX_TRADE_SLOTS {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.inv_textslots
|
|
|
|
.resize(2 * MAX_TRADE_SLOTS, &mut ui.widget_id_generator());
|
|
|
|
});
|
|
|
|
}
|
2024-03-27 14:55:12 +00:00
|
|
|
let max_width = 170.0;
|
|
|
|
let mut total_text_height = 0.0;
|
2021-05-07 02:47:55 +00:00
|
|
|
let mut total_quantity = 0;
|
2021-02-12 10:51:32 +00:00
|
|
|
for i in 0..MAX_TRADE_SLOTS {
|
|
|
|
let slot = tradeslots.get(i).cloned().unwrap_or(TradeSlot {
|
|
|
|
index: i,
|
|
|
|
quantity: 0,
|
|
|
|
invslot: None,
|
2021-02-28 02:44:57 +00:00
|
|
|
ours,
|
|
|
|
entity,
|
2021-02-12 10:51:32 +00:00
|
|
|
});
|
2021-05-07 02:47:55 +00:00
|
|
|
total_quantity += slot.quantity;
|
2021-02-12 10:51:32 +00:00
|
|
|
let itemname = slot
|
|
|
|
.invslot
|
|
|
|
.and_then(|i| inventory.get(i))
|
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
|
|
|
.map(|i| {
|
2024-01-16 16:40:12 +00:00
|
|
|
let (name, _) = util::item_text(&i, self.localized_strings, self.item_i18n);
|
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
|
|
|
|
|
|
|
Cow::Owned(name)
|
|
|
|
})
|
2021-07-31 23:37:45 +00:00
|
|
|
.unwrap_or(Cow::Borrowed(""));
|
2021-02-12 10:51:32 +00:00
|
|
|
let is_present = slot.quantity > 0 && slot.invslot.is_some();
|
2024-03-27 14:55:12 +00:00
|
|
|
Text::new(&format!("{}x {}", slot.quantity, &itemname))
|
|
|
|
.top_left_with_margins_on(
|
|
|
|
state.ids.inv_alignment[who],
|
|
|
|
15.0 + i as f64 * 20.0 + total_text_height,
|
|
|
|
0.0,
|
|
|
|
)
|
2021-02-12 10:51:32 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
2024-03-27 14:55:12 +00:00
|
|
|
.wrap_by_word()
|
|
|
|
.w(max_width)
|
2021-02-12 23:09:18 +00:00
|
|
|
.color(Color::Rgba(
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
if is_present { 1.0 } else { 0.0 },
|
|
|
|
))
|
2021-02-12 10:51:32 +00:00
|
|
|
.set(state.ids.inv_textslots[i + who * MAX_TRADE_SLOTS], ui);
|
2024-03-27 14:55:12 +00:00
|
|
|
let label_height = match ui
|
|
|
|
.widget_graph()
|
|
|
|
.widget(state.ids.inv_textslots[i + who * MAX_TRADE_SLOTS])
|
|
|
|
.map(|widget| widget.rect)
|
|
|
|
{
|
|
|
|
Some(label_rect) => label_rect.h(),
|
|
|
|
None => 10.0,
|
|
|
|
};
|
|
|
|
total_text_height += label_height;
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
2021-05-07 02:47:55 +00:00
|
|
|
if total_quantity == 0 {
|
|
|
|
Text::new("Nothing!")
|
|
|
|
.top_left_with_margins_on(state.ids.inv_alignment[who], 10.0, 0.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.color(Color::Rgba(
|
|
|
|
1.0,
|
|
|
|
0.25 + 0.25 * (4.0 * self.pulse).sin(),
|
|
|
|
0.0,
|
|
|
|
1.0,
|
|
|
|
))
|
|
|
|
.set(state.ids.inv_textslots[who * MAX_TRADE_SLOTS], ui);
|
2023-06-26 14:39:30 +00:00
|
|
|
|
|
|
|
if !ours {
|
|
|
|
self.needs_thirdconfirm = true;
|
|
|
|
}
|
2021-05-07 02:47:55 +00:00
|
|
|
}
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn accept_decline_buttons(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
|
|
|
trade: &'a PendingTrade,
|
2023-01-12 23:26:50 +00:00
|
|
|
) -> Option<TradeEvent> {
|
2021-02-12 10:51:32 +00:00
|
|
|
let mut event = None;
|
2022-02-16 21:41:26 +00:00
|
|
|
let (hover_img, press_img, accept_button_luminance) = if trade.is_empty_trade() {
|
|
|
|
//Darken the accept button if the trade is empty.
|
|
|
|
(
|
|
|
|
self.imgs.button,
|
|
|
|
self.imgs.button,
|
|
|
|
Color::Rgba(0.6, 0.6, 0.6, 1.0),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
self.imgs.button_hover,
|
|
|
|
self.imgs.button_press,
|
|
|
|
Color::Rgba(1.0, 1.0, 1.0, 1.0),
|
|
|
|
)
|
|
|
|
};
|
2021-02-12 10:51:32 +00:00
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(31.0 * 5.0, 12.0 * 2.0)
|
2022-02-16 21:41:26 +00:00
|
|
|
.hover_image(hover_img)
|
|
|
|
.press_image(press_img)
|
|
|
|
.image_color(accept_button_luminance)
|
2021-08-08 11:45:26 +00:00
|
|
|
.bottom_left_with_margins_on(state.ids.bg, 90.0, 47.0)
|
2022-08-23 11:14:29 +00:00
|
|
|
.label(&self.localized_strings.get_msg("hud-trade-accept"))
|
2021-02-12 10:51:32 +00:00
|
|
|
.label_font_size(self.fonts.cyri.scale(14))
|
|
|
|
.label_color(TEXT_COLOR)
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_y(Relative::Scalar(2.0))
|
|
|
|
.set(state.ids.accept_button, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2023-06-26 14:39:30 +00:00
|
|
|
if matches!(trade.phase, TradePhase::Review) && self.needs_thirdconfirm {
|
|
|
|
event = Some(TradeEvent::ShowPrompt(PromptDialogSettings::new(
|
|
|
|
self.localized_strings
|
|
|
|
.get_msg("hud-confirm-trade-for-nothing")
|
|
|
|
.to_string(),
|
|
|
|
HudEvent::TradeAction(TradeAction::Accept(trade.phase())),
|
|
|
|
None,
|
|
|
|
)));
|
|
|
|
} else {
|
|
|
|
event = Some(TradeEvent::TradeAction(TradeAction::Accept(trade.phase())));
|
|
|
|
}
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(31.0 * 5.0, 12.0 * 2.0)
|
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.right_from(state.ids.accept_button, 20.0)
|
2022-08-23 11:14:29 +00:00
|
|
|
.label(&self.localized_strings.get_msg("hud-trade-decline"))
|
2021-02-12 10:51:32 +00:00
|
|
|
.label_font_size(self.fonts.cyri.scale(14))
|
|
|
|
.label_color(TEXT_COLOR)
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_y(Relative::Scalar(2.0))
|
|
|
|
.set(state.ids.decline_button, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2023-06-26 14:39:30 +00:00
|
|
|
event = Some(TradeEvent::TradeAction(TradeAction::Decline));
|
2021-02-12 10:51:32 +00:00
|
|
|
}
|
2023-06-26 14:39:30 +00:00
|
|
|
event
|
2021-02-12 02:53:25 +00:00
|
|
|
}
|
|
|
|
|
2022-03-06 06:18:25 +00:00
|
|
|
fn input_item_amount(
|
2021-02-12 02:53:25 +00:00
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
2022-03-06 06:18:25 +00:00
|
|
|
trade: &'a PendingTrade,
|
2023-01-12 23:26:50 +00:00
|
|
|
) -> Option<TradeEvent> {
|
2022-03-06 06:18:25 +00:00
|
|
|
let mut event = None;
|
|
|
|
let selected = self.slot_manager.selected().and_then(|s| match s {
|
|
|
|
SlotKind::Trade(t_s) => t_s.invslot.and_then(|slot| {
|
|
|
|
let who: usize = trade.offers[0].get(&slot).and(Some(0)).unwrap_or(1);
|
|
|
|
self.client
|
|
|
|
.inventories()
|
|
|
|
.get(t_s.entity)?
|
|
|
|
.get(slot)
|
2022-03-06 06:18:25 +00:00
|
|
|
.map(|item| (t_s.ours, slot, item.amount(), who))
|
2022-03-06 06:18:25 +00:00
|
|
|
}),
|
|
|
|
_ => None,
|
|
|
|
});
|
|
|
|
Rectangle::fill([132.0, 20.0])
|
|
|
|
.bottom_right_with_margins_on(state.ids.bg_frame, 16.0, 32.0)
|
|
|
|
.hsla(
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
if self.show.trade_amount_input_key.is_some() {
|
|
|
|
0.75
|
|
|
|
} else {
|
|
|
|
0.35
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.set(state.ids.amount_bg, ui);
|
|
|
|
if let Some((ours, slot, inv, who)) = selected {
|
2022-03-08 07:35:09 +00:00
|
|
|
self.show.trade_amount_input_key = None;
|
2022-03-06 06:18:25 +00:00
|
|
|
// Text for the amount of items offered.
|
|
|
|
let input = trade.offers[who]
|
|
|
|
.get(&slot)
|
2022-03-06 06:18:25 +00:00
|
|
|
.map(|u| format!("{}", u))
|
|
|
|
.unwrap_or_else(String::new);
|
2022-03-06 06:18:25 +00:00
|
|
|
Text::new(&input)
|
|
|
|
.top_left_with_margins_on(state.ids.amount_bg, 0.0, 22.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.color(TEXT_COLOR.alpha(0.7))
|
|
|
|
.set(state.ids.amount_open_label, ui);
|
|
|
|
if Button::image(self.imgs.edit_btn)
|
|
|
|
.hover_image(self.imgs.edit_btn_hover)
|
|
|
|
.press_image(self.imgs.edit_btn_press)
|
|
|
|
.mid_left_with_margin_on(state.ids.amount_bg, 2.0)
|
|
|
|
.w_h(16.0, 16.0)
|
|
|
|
.set(state.ids.amount_open_btn, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2022-03-08 07:35:09 +00:00
|
|
|
event = Some(HudUpdate::Focus(state.ids.amount_input));
|
2022-03-06 06:18:25 +00:00
|
|
|
self.slot_manager.idle();
|
|
|
|
self.show.trade_amount_input_key =
|
|
|
|
Some(TradeAmountInput::new(slot, input, inv, ours, who));
|
|
|
|
}
|
|
|
|
Rectangle::fill_with([132.0, 20.0], color::TRANSPARENT)
|
|
|
|
.top_left_of(state.ids.amount_bg)
|
|
|
|
.graphics_for(state.ids.amount_open_btn)
|
|
|
|
.set(state.ids.amount_open_ovlay, ui);
|
|
|
|
} else if let Some(key) = &mut self.show.trade_amount_input_key {
|
2022-07-15 12:08:04 +00:00
|
|
|
if !Hud::is_captured::<TextEdit>(ui) && key.input_painted {
|
2022-03-08 07:35:09 +00:00
|
|
|
// If the text edit is not captured submit the amount.
|
|
|
|
event = Some(HudUpdate::Submit);
|
2022-03-06 06:18:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if Button::image(self.imgs.close_btn)
|
|
|
|
.hover_image(self.imgs.close_btn_hover)
|
|
|
|
.press_image(self.imgs.close_btn_press)
|
|
|
|
.mid_left_with_margin_on(state.ids.amount_bg, 2.0)
|
|
|
|
.w_h(16.0, 16.0)
|
|
|
|
.set(state.ids.amount_btn, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2022-03-08 07:35:09 +00:00
|
|
|
event = Some(HudUpdate::Submit);
|
2022-03-06 06:18:25 +00:00
|
|
|
}
|
|
|
|
// Input for making TradeAction requests
|
2022-03-08 07:35:09 +00:00
|
|
|
key.input_painted = true;
|
2022-03-06 06:18:25 +00:00
|
|
|
let text_color = key.err.as_ref().and(Some(color::RED)).unwrap_or(TEXT_COLOR);
|
|
|
|
if let Some(new_input) = TextEdit::new(&key.input)
|
|
|
|
.mid_left_with_margin_on(state.ids.amount_bg, 22.0)
|
|
|
|
.w_h(138.0, 20.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.color(text_color)
|
|
|
|
.set(state.ids.amount_input, ui)
|
|
|
|
{
|
|
|
|
if new_input != key.input {
|
|
|
|
key.input = new_input.trim().to_owned();
|
|
|
|
if !key.input.is_empty() {
|
|
|
|
// trade amount can change with (shift||ctrl)-click
|
2022-03-06 22:39:01 +00:00
|
|
|
let amount = *trade.offers[key.who].get(&key.slot).unwrap_or(&0);
|
2022-03-06 06:18:25 +00:00
|
|
|
match key.input.parse::<i32>() {
|
|
|
|
Ok(new_amount) => {
|
|
|
|
key.input = format!("{}", new_amount);
|
|
|
|
if new_amount > -1 && new_amount <= key.inv as i32 {
|
|
|
|
key.err = None;
|
2022-03-06 22:39:01 +00:00
|
|
|
let delta = new_amount - amount as i32;
|
2022-03-08 07:35:09 +00:00
|
|
|
key.submit_action =
|
|
|
|
TradeAction::item(key.slot, delta, key.ours);
|
2022-03-06 06:18:25 +00:00
|
|
|
} else {
|
|
|
|
key.err = Some("out of range".to_owned());
|
2022-03-08 07:35:09 +00:00
|
|
|
key.submit_action = None;
|
2022-03-06 06:18:25 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
key.err = Some("bad quantity".to_owned());
|
2022-03-08 07:35:09 +00:00
|
|
|
key.submit_action = None;
|
2022-03-06 06:18:25 +00:00
|
|
|
},
|
|
|
|
}
|
2022-03-08 07:35:09 +00:00
|
|
|
} else {
|
|
|
|
key.submit_action = None;
|
2022-03-06 06:18:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// placeholder text when no trade slot is selected
|
2022-08-23 11:14:29 +00:00
|
|
|
Text::new(&self.localized_strings.get_msg("hud-trade-amount_input"))
|
2022-03-06 06:18:25 +00:00
|
|
|
.middle_of(state.ids.amount_bg)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.color(TEXT_GRAY_COLOR.alpha(0.25))
|
|
|
|
.set(state.ids.amount_notice, ui);
|
|
|
|
}
|
2023-01-12 23:26:50 +00:00
|
|
|
event.map(TradeEvent::HudUpdate)
|
2022-03-06 06:18:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn close_button(
|
|
|
|
&mut self,
|
|
|
|
state: &mut ConrodState<'_, State>,
|
|
|
|
ui: &mut UiCell<'_>,
|
2023-01-12 23:26:50 +00:00
|
|
|
) -> Option<TradeEvent> {
|
2021-02-12 02:53:25 +00:00
|
|
|
if Button::image(self.imgs.close_btn)
|
2021-02-12 10:51:32 +00:00
|
|
|
.w_h(24.0, 25.0)
|
2021-02-12 02:53:25 +00:00
|
|
|
.hover_image(self.imgs.close_btn_hover)
|
|
|
|
.press_image(self.imgs.close_btn_press)
|
|
|
|
.top_right_with_margins_on(state.ids.bg, 0.0, 0.0)
|
|
|
|
.set(state.ids.trade_close, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2023-01-12 23:26:50 +00:00
|
|
|
Some(TradeEvent::TradeAction(TradeAction::Decline))
|
2021-02-12 02:53:25 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 04:44:49 +00:00
|
|
|
impl<'a> Widget for Trade<'a> {
|
2023-01-12 23:26:50 +00:00
|
|
|
type Event = Option<TradeEvent>;
|
2021-02-10 04:44:49 +00:00
|
|
|
type State = State;
|
|
|
|
type Style = ();
|
|
|
|
|
2021-02-28 02:44:57 +00:00
|
|
|
fn init_state(&self, mut id_gen: widget::id::Generator) -> Self::State {
|
2021-02-10 04:44:49 +00:00
|
|
|
State {
|
2021-02-28 02:44:57 +00:00
|
|
|
bg_ids: BackgroundIds {
|
|
|
|
bg: id_gen.next(),
|
|
|
|
bg_frame: id_gen.next(),
|
|
|
|
},
|
2021-02-10 04:44:49 +00:00
|
|
|
ids: Ids::new(id_gen),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn style(&self) -> Self::Style {}
|
|
|
|
|
2021-02-12 02:53:25 +00:00
|
|
|
fn update(mut self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
2021-06-19 05:04:05 +00:00
|
|
|
common_base::prof_span!("Trade::update");
|
2021-11-24 09:09:22 +00:00
|
|
|
let widget::UpdateArgs { state, ui, .. } = args;
|
2021-02-10 04:44:49 +00:00
|
|
|
|
|
|
|
let mut event = None;
|
2021-03-25 04:35:33 +00:00
|
|
|
let (trade, prices) = match self.client.pending_trade() {
|
|
|
|
Some((_, trade, prices)) => (trade, prices),
|
2023-01-12 23:26:50 +00:00
|
|
|
None => return Some(TradeEvent::TradeAction(TradeAction::Decline)),
|
2021-02-10 04:44:49 +00:00
|
|
|
};
|
|
|
|
|
2021-02-12 02:53:25 +00:00
|
|
|
if state.ids.inv_alignment.len() < 2 {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids.inv_alignment.resize(2, &mut ui.widget_id_generator());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if state.ids.offer_headers.len() < 2 {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids.offer_headers.resize(2, &mut ui.widget_id_generator());
|
|
|
|
});
|
|
|
|
}
|
2021-02-12 10:51:32 +00:00
|
|
|
if state.ids.accept_indicators.len() < 2 {
|
|
|
|
state.update(|s| {
|
2021-02-12 23:09:18 +00:00
|
|
|
s.ids
|
|
|
|
.accept_indicators
|
|
|
|
.resize(2, &mut ui.widget_id_generator());
|
2021-02-12 10:51:32 +00:00
|
|
|
});
|
|
|
|
}
|
2021-02-12 02:53:25 +00:00
|
|
|
|
2021-11-24 09:09:22 +00:00
|
|
|
self.background(state, ui);
|
|
|
|
self.title(state, ui);
|
|
|
|
self.phase_indicator(state, ui, trade);
|
|
|
|
|
|
|
|
event = self.item_pane(state, ui, trade, prices, false).or(event);
|
|
|
|
event = self.item_pane(state, ui, trade, prices, true).or(event);
|
|
|
|
event = self.accept_decline_buttons(state, ui, trade).or(event);
|
|
|
|
event = self.close_button(state, ui).or(event);
|
2023-01-12 23:26:50 +00:00
|
|
|
self.input_item_amount(state, ui, trade).or(event)
|
2021-02-10 04:44:49 +00:00
|
|
|
}
|
|
|
|
}
|