mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'hqurve/crafting-ui' into 'master'
Added search to crafting and social windows, added i18n support to crafting tabs, fixed social window offset when group open, removed tabs in social window See merge request veloren/veloren!2081
This commit is contained in:
commit
fd77966293
@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Crafting menu tabs
|
||||
- Auto camera setting, making the game easier to play with one hand
|
||||
- Topographic map option
|
||||
- Search bars for social and crafting window
|
||||
|
||||
### Changed
|
||||
|
||||
@ -48,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added a raycast check to beams to prevent their effect applying through walls
|
||||
- Flying agents raycast more angles to check for obstacles.
|
||||
- Mouse Cursor now locks to the center of the screen when menu is not open
|
||||
- Social window no longer moves when group is open
|
||||
|
||||
## [0.9.0] - 2021-03-20
|
||||
|
||||
|
BIN
assets/voxygen/element/buttons/search_btn.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/search_btn.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/buttons/search_btn_hover.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/search_btn_hover.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/buttons/search_btn_press.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/search_btn_press.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab_active.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab_active.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab_hover.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab_hover.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab_inactive.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab_inactive.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab_press.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab_press.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/social_tab_pressed.png
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/social_tab_pressed.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/icons/globe.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/globe.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/globe_2.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/globe_2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/crafting.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/crafting.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/crafting_frame.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/crafting_frame.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/social_bg.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/social_bg.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/social_frame.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/social_frame.png
(Stored with Git LFS)
Binary file not shown.
@ -8,6 +8,18 @@
|
||||
"hud.crafting.ingredients": "Ingredients:",
|
||||
"hud.crafting.craft": "Craft",
|
||||
"hud.crafting.tool_cata": "Requires:",
|
||||
|
||||
// Tabs
|
||||
"hud.crafting.tabs.all": "All",
|
||||
"hud.crafting.tabs.armor": "Armor",
|
||||
"hud.crafting.tabs.dismantle": "Dismantle",
|
||||
"hud.crafting.tabs.food": "Food",
|
||||
"hud.crafting.tabs.glider": "Gliders",
|
||||
"hud.crafting.tabs.potion": "Potions",
|
||||
"hud.crafting.tabs.tool": "Tools",
|
||||
"hud.crafting.tabs.utility": "Utility",
|
||||
"hud.crafting.tabs.weapon": "Weapons",
|
||||
"hud.crafting.tabs.bag": "Bags",
|
||||
},
|
||||
|
||||
|
||||
|
@ -22,8 +22,8 @@ use common::{
|
||||
recipe::RecipeInput,
|
||||
};
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
||||
color, image,
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text, TextEdit},
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@ -41,7 +41,13 @@ widget_ids! {
|
||||
title_rec,
|
||||
align_rec,
|
||||
scrollbar_rec,
|
||||
btn_open_search,
|
||||
btn_close_search,
|
||||
input_search,
|
||||
input_bg_search,
|
||||
input_overlay_search,
|
||||
title_ing,
|
||||
tags_ing[],
|
||||
align_ing,
|
||||
scrollbar_ing,
|
||||
btn_craft,
|
||||
@ -64,8 +70,10 @@ widget_ids! {
|
||||
|
||||
pub enum Event {
|
||||
CraftRecipe(String),
|
||||
ChangeCraftingTab(SelectedCraftingTab),
|
||||
ChangeCraftingTab(CraftingTab),
|
||||
Close,
|
||||
Focus(widget::Id),
|
||||
SearchRecipe(Option<String>),
|
||||
}
|
||||
|
||||
#[derive(WidgetCommon)]
|
||||
@ -120,7 +128,8 @@ impl<'a> Crafting<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumIter, PartialEq)]
|
||||
pub enum SelectedCraftingTab {
|
||||
pub enum CraftingTab {
|
||||
All,
|
||||
Armor,
|
||||
Weapon,
|
||||
Food,
|
||||
@ -131,6 +140,61 @@ pub enum SelectedCraftingTab {
|
||||
Utility,
|
||||
Glider,
|
||||
}
|
||||
impl CraftingTab {
|
||||
fn name_key(&self) -> &str {
|
||||
match self {
|
||||
CraftingTab::All => "hud.crafting.tabs.all",
|
||||
CraftingTab::Armor => "hud.crafting.tabs.armor",
|
||||
CraftingTab::Dismantle => "hud.crafting.tabs.dismantle",
|
||||
CraftingTab::Food => "hud.crafting.tabs.food",
|
||||
CraftingTab::Glider => "hud.crafting.tabs.glider",
|
||||
CraftingTab::Potion => "hud.crafting.tabs.potion",
|
||||
CraftingTab::Tool => "hud.crafting.tabs.tool",
|
||||
CraftingTab::Utility => "hud.crafting.tabs.utility",
|
||||
CraftingTab::Weapon => "hud.crafting.tabs.weapon",
|
||||
CraftingTab::Bag => "hud.crafting.tabs.bag",
|
||||
}
|
||||
}
|
||||
|
||||
fn img_id(&self, imgs: &Imgs) -> image::Id {
|
||||
match self {
|
||||
CraftingTab::All => imgs.icon_globe,
|
||||
CraftingTab::Armor => imgs.icon_armor,
|
||||
CraftingTab::Dismantle => imgs.icon_dismantle,
|
||||
CraftingTab::Food => imgs.icon_food,
|
||||
CraftingTab::Glider => imgs.icon_glider,
|
||||
CraftingTab::Potion => imgs.icon_potion,
|
||||
CraftingTab::Tool => imgs.icon_tools,
|
||||
CraftingTab::Utility => imgs.icon_utility,
|
||||
CraftingTab::Weapon => imgs.icon_weapon,
|
||||
CraftingTab::Bag => imgs.icon_bag,
|
||||
}
|
||||
}
|
||||
|
||||
fn satisfies(&self, item: &ItemDef) -> bool {
|
||||
match self {
|
||||
CraftingTab::All => true,
|
||||
CraftingTab::Food => item.tags().contains(&ItemTag::Food),
|
||||
CraftingTab::Armor => match item.kind() {
|
||||
ItemKind::Armor(_) => !item.tags().contains(&ItemTag::Bag),
|
||||
_ => false,
|
||||
},
|
||||
CraftingTab::Glider => matches!(item.kind(), ItemKind::Glider(_)),
|
||||
CraftingTab::Potion => item.tags().contains(&ItemTag::Potion),
|
||||
CraftingTab::Bag => item.tags().contains(&ItemTag::Bag),
|
||||
CraftingTab::Tool => item.tags().contains(&ItemTag::CraftingTool),
|
||||
CraftingTab::Utility => item.tags().contains(&ItemTag::Utility),
|
||||
CraftingTab::Weapon => match item.kind() {
|
||||
ItemKind::Tool(_) => !item.tags().contains(&ItemTag::CraftingTool),
|
||||
_ => false,
|
||||
},
|
||||
CraftingTab::Dismantle => match item.kind() {
|
||||
ItemKind::Ingredient { .. } => !item.tags().contains(&ItemTag::CraftingTool),
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
ids: Ids,
|
||||
@ -155,15 +219,6 @@ impl<'a> Widget for Crafting<'a> {
|
||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||
let widget::UpdateArgs { state, ui, .. } = args;
|
||||
|
||||
if state.ids.recipe_names.len() < self.client.recipe_book().iter().len() {
|
||||
state.update(|state| {
|
||||
state.ids.recipe_names.resize(
|
||||
self.client.recipe_book().iter().len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
let mut events = Vec::new();
|
||||
|
||||
// Tooltips
|
||||
@ -211,21 +266,36 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.desc_text_color(TEXT_COLOR);
|
||||
|
||||
// Frame and window
|
||||
Image::new(self.imgs.crafting_window)
|
||||
.bottom_right_with_margins_on(ui.window, 308.0, 450.0)
|
||||
.color(Some(UI_MAIN))
|
||||
.w_h(422.0, 460.0)
|
||||
.set(state.ids.window, ui);
|
||||
// Search Background
|
||||
// I couldn't find a way to manually set they layer of a widget
|
||||
// If it is possible, please move this code (for rectangle) down to the code for
|
||||
// search input
|
||||
if self.show.crafting_search_key.is_some() {
|
||||
Rectangle::fill([114.0, 20.0])
|
||||
.top_left_with_margins_on(state.ids.window, 52.0, 26.0)
|
||||
.hsla(0.0, 0.0, 0.0, 0.7)
|
||||
.set(state.ids.input_bg_search, ui);
|
||||
}
|
||||
// Window
|
||||
Image::new(self.imgs.crafting_frame)
|
||||
.middle_of(state.ids.window)
|
||||
.color(Some(UI_HIGHLIGHT_0))
|
||||
.w_h(422.0, 460.0)
|
||||
.set(state.ids.window_frame, ui);
|
||||
|
||||
// Crafting Icon
|
||||
Image::new(self.imgs.crafting_icon_bordered)
|
||||
.w_h(38.0, 38.0)
|
||||
.top_left_with_margins_on(state.ids.window_frame, 4.0, 4.0)
|
||||
.set(state.ids.icon, ui);
|
||||
// Close Button
|
||||
|
||||
// Close Button
|
||||
if Button::image(self.imgs.close_button)
|
||||
.w_h(24.0, 25.0)
|
||||
.hover_image(self.imgs.close_button_hover)
|
||||
@ -254,105 +324,83 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.top_right_with_margins_on(state.ids.window, 74.0, 5.0)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.align_ing, ui);
|
||||
|
||||
// Category Tabs
|
||||
if state.ids.category_bgs.len() < SelectedCraftingTab::iter().enumerate().len() {
|
||||
if state.ids.category_bgs.len() < CraftingTab::iter().enumerate().len() {
|
||||
state.update(|s| {
|
||||
s.ids.category_bgs.resize(
|
||||
SelectedCraftingTab::iter().enumerate().len(),
|
||||
CraftingTab::iter().enumerate().len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
})
|
||||
};
|
||||
if state.ids.category_tabs.len() < SelectedCraftingTab::iter().enumerate().len() {
|
||||
if state.ids.category_tabs.len() < CraftingTab::iter().enumerate().len() {
|
||||
state.update(|s| {
|
||||
s.ids.category_tabs.resize(
|
||||
SelectedCraftingTab::iter().enumerate().len(),
|
||||
CraftingTab::iter().enumerate().len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
})
|
||||
};
|
||||
if state.ids.category_imgs.len() < SelectedCraftingTab::iter().enumerate().len() {
|
||||
if state.ids.category_imgs.len() < CraftingTab::iter().enumerate().len() {
|
||||
state.update(|s| {
|
||||
s.ids.category_imgs.resize(
|
||||
SelectedCraftingTab::iter().enumerate().len(),
|
||||
CraftingTab::iter().enumerate().len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
})
|
||||
};
|
||||
let sel_crafting_tab = &self.show.crafting_tab;
|
||||
for i in SelectedCraftingTab::iter().enumerate() {
|
||||
// TODO: i18n!
|
||||
let tab_name = match i.1 {
|
||||
SelectedCraftingTab::Armor => "Armor",
|
||||
SelectedCraftingTab::Dismantle => "Dismantle",
|
||||
SelectedCraftingTab::Food => "Food",
|
||||
SelectedCraftingTab::Glider => "Gliders",
|
||||
SelectedCraftingTab::Potion => "Potions",
|
||||
SelectedCraftingTab::Tool => "Tools",
|
||||
SelectedCraftingTab::Utility => "Utility",
|
||||
SelectedCraftingTab::Weapon => "Weapons",
|
||||
SelectedCraftingTab::Bag => "Bags",
|
||||
};
|
||||
let tab_img = match i.1 {
|
||||
SelectedCraftingTab::Armor => self.imgs.icon_armor,
|
||||
SelectedCraftingTab::Dismantle => self.imgs.icon_dismantle,
|
||||
SelectedCraftingTab::Food => self.imgs.icon_food,
|
||||
SelectedCraftingTab::Glider => self.imgs.icon_glider,
|
||||
SelectedCraftingTab::Potion => self.imgs.icon_potion,
|
||||
SelectedCraftingTab::Tool => self.imgs.icon_tools,
|
||||
SelectedCraftingTab::Utility => self.imgs.icon_utility,
|
||||
SelectedCraftingTab::Weapon => self.imgs.icon_weapon,
|
||||
SelectedCraftingTab::Bag => self.imgs.icon_bag,
|
||||
};
|
||||
for (i, crafting_tab) in CraftingTab::iter().enumerate() {
|
||||
let tab_img = crafting_tab.img_id(self.imgs);
|
||||
// Button Background
|
||||
let mut bg = Image::new(self.imgs.pixel)
|
||||
.w_h(40.0, 30.0)
|
||||
.color(Some(UI_MAIN));
|
||||
if i.0 == 0 {
|
||||
if i == 0 {
|
||||
bg = bg.top_left_with_margins_on(state.ids.window_frame, 50.0, -40.0)
|
||||
} else {
|
||||
bg = bg.down_from(state.ids.category_bgs[i.0 - 1], 0.0)
|
||||
bg = bg.down_from(state.ids.category_bgs[i - 1], 0.0)
|
||||
};
|
||||
bg.set(state.ids.category_bgs[i.0], ui);
|
||||
bg.set(state.ids.category_bgs[i], ui);
|
||||
// Category Button
|
||||
if Button::image(if i.1 == *sel_crafting_tab {
|
||||
if Button::image(if crafting_tab == *sel_crafting_tab {
|
||||
self.imgs.wpn_icon_border_pressed
|
||||
} else {
|
||||
self.imgs.wpn_icon_border
|
||||
})
|
||||
.wh_of(state.ids.category_bgs[i.0])
|
||||
.middle_of(state.ids.category_bgs[i.0])
|
||||
.hover_image(if i.1 == *sel_crafting_tab {
|
||||
.wh_of(state.ids.category_bgs[i])
|
||||
.middle_of(state.ids.category_bgs[i])
|
||||
.hover_image(if crafting_tab == *sel_crafting_tab {
|
||||
self.imgs.wpn_icon_border_pressed
|
||||
} else {
|
||||
self.imgs.wpn_icon_border_mo
|
||||
})
|
||||
.press_image(if i.1 == *sel_crafting_tab {
|
||||
.press_image(if crafting_tab == *sel_crafting_tab {
|
||||
self.imgs.wpn_icon_border_pressed
|
||||
} else {
|
||||
self.imgs.wpn_icon_border_press
|
||||
})
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
tab_name,
|
||||
&self.localized_strings.get(crafting_tab.name_key()),
|
||||
"",
|
||||
&tabs_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.category_tabs[i.0], ui)
|
||||
.set(state.ids.category_tabs[i], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeCraftingTab(i.1))
|
||||
events.push(Event::ChangeCraftingTab(crafting_tab))
|
||||
};
|
||||
// Tab images
|
||||
Image::new(tab_img)
|
||||
.middle_of(state.ids.category_tabs[i.0])
|
||||
.middle_of(state.ids.category_tabs[i])
|
||||
.w_h(20.0, 20.0)
|
||||
.graphics_for(state.ids.category_tabs[i.0])
|
||||
.set(state.ids.category_imgs[i.0], ui);
|
||||
.graphics_for(state.ids.category_tabs[i])
|
||||
.set(state.ids.category_imgs[i], ui);
|
||||
}
|
||||
|
||||
let client = &self.client;
|
||||
// First available recipes, then unavailable ones, each alphabetically
|
||||
// In the triples, "name" is the recipe book key, and "recipe.output.0.name()"
|
||||
// is the display name (as stored in the item descriptors)
|
||||
@ -366,6 +414,17 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.client
|
||||
.recipe_book()
|
||||
.iter()
|
||||
.filter(|(_, recipe)| {
|
||||
let output_name = recipe.output.0.name.to_lowercase();
|
||||
if let Some(key) = &self.show.crafting_search_key {
|
||||
key.as_str()
|
||||
.to_lowercase()
|
||||
.split_whitespace()
|
||||
.all(|substring| output_name.contains(substring))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|(name, recipe)| {
|
||||
let at_least_some_ingredients = recipe.inputs.iter().any(|(input, amount)| {
|
||||
*amount > 0
|
||||
@ -375,7 +434,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.unwrap_or(false)
|
||||
})
|
||||
});
|
||||
let state = if client.available_recipes().contains(name.as_str()) {
|
||||
let state = if self.client.available_recipes().contains(name.as_str()) {
|
||||
RecipeIngredientQuantity::All
|
||||
} else if at_least_some_ingredients {
|
||||
RecipeIngredientQuantity::Some
|
||||
@ -386,129 +445,19 @@ impl<'a> Widget for Crafting<'a> {
|
||||
})
|
||||
.collect();
|
||||
ordered_recipes.sort_by_key(|(_, recipe, state)| (*state, recipe.output.0.name()));
|
||||
match &state.selected_recipe {
|
||||
None => {},
|
||||
Some(recipe) => {
|
||||
let can_perform = client.available_recipes().contains(recipe.as_str());
|
||||
// Ingredients Text
|
||||
Text::new(&self.localized_strings.get("hud.crafting.ingredients"))
|
||||
.top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.ingredients_txt, ui);
|
||||
// Craft button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(105.0, 25.0)
|
||||
.hover_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_hover)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.press_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_press)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.label(&self.localized_strings.get("hud.crafting.craft"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR))
|
||||
.label_font_size(self.fonts.cyri.scale(12))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.image_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR))
|
||||
.mid_bottom_with_margin_on(state.ids.align_ing, -31.0)
|
||||
.parent(state.ids.window_frame)
|
||||
.set(state.ids.btn_craft, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::CraftRecipe(recipe.clone()));
|
||||
}
|
||||
// Result Image BG
|
||||
let quality_col_img = if let Some(recipe) = state
|
||||
.selected_recipe
|
||||
.as_ref()
|
||||
.and_then(|r| self.client.recipe_book().get(r.as_str()))
|
||||
{
|
||||
match recipe.output.0.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,
|
||||
}
|
||||
} else {
|
||||
self.imgs.inv_slot
|
||||
};
|
||||
Image::new(quality_col_img)
|
||||
.w_h(60.0, 60.0)
|
||||
.top_right_with_margins_on(state.ids.align_ing, 15.0, 10.0)
|
||||
.parent(state.ids.align_ing)
|
||||
.set(state.ids.output_img_frame, ui);
|
||||
|
||||
if let Some(recipe) = state
|
||||
.selected_recipe
|
||||
.as_ref()
|
||||
.and_then(|r| self.client.recipe_book().get(r.as_str()))
|
||||
{
|
||||
let output_text = format!("x{}", &recipe.output.1.to_string());
|
||||
// Output Image
|
||||
Button::image(animate_by_pulse(
|
||||
&self
|
||||
.item_imgs
|
||||
.img_ids_or_not_found_img((&*recipe.output.0).into()),
|
||||
self.pulse,
|
||||
))
|
||||
.w_h(55.0, 55.0)
|
||||
.label(&output_text)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(conrod_core::position::Relative::Scalar(-24.0))
|
||||
.label_x(conrod_core::position::Relative::Scalar(24.0))
|
||||
.middle_of(state.ids.output_img_frame)
|
||||
.with_item_tooltip(
|
||||
self.item_tooltip_manager,
|
||||
&*recipe.output.0,
|
||||
&None,
|
||||
&item_tooltip,
|
||||
)
|
||||
.set(state.ids.output_img, ui);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Recipe list
|
||||
if state.ids.recipe_names.len() < self.client.recipe_book().iter().len() {
|
||||
state.update(|state| {
|
||||
state.ids.recipe_names.resize(
|
||||
self.client.recipe_book().iter().len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
});
|
||||
}
|
||||
for (i, (name, recipe, quantity)) in ordered_recipes
|
||||
.into_iter()
|
||||
.filter(|(_name, recipe, _quantity)| match &self.show.crafting_tab {
|
||||
SelectedCraftingTab::Food => recipe.output.0.tags().contains(&ItemTag::Food),
|
||||
SelectedCraftingTab::Armor => match recipe.output.0.kind() {
|
||||
ItemKind::Armor(_) => !recipe.output.0.tags().contains(&ItemTag::Bag),
|
||||
_ => false,
|
||||
},
|
||||
SelectedCraftingTab::Glider => {
|
||||
matches!(recipe.output.0.kind(), ItemKind::Glider(_))
|
||||
},
|
||||
SelectedCraftingTab::Potion => recipe.output.0.tags().contains(&ItemTag::Potion),
|
||||
SelectedCraftingTab::Bag => recipe.output.0.tags().contains(&ItemTag::Bag),
|
||||
SelectedCraftingTab::Tool => {
|
||||
recipe.output.0.tags().contains(&ItemTag::CraftingTool)
|
||||
},
|
||||
SelectedCraftingTab::Utility => recipe.output.0.tags().contains(&ItemTag::Utility),
|
||||
SelectedCraftingTab::Weapon => match recipe.output.0.kind() {
|
||||
ItemKind::Tool(_) => !recipe.output.0.tags().contains(&ItemTag::CraftingTool),
|
||||
_ => false,
|
||||
},
|
||||
SelectedCraftingTab::Dismantle => match recipe.output.0.kind() {
|
||||
ItemKind::Ingredient { .. } => {
|
||||
!recipe.output.0.tags().contains(&ItemTag::CraftingTool)
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
})
|
||||
.filter(|(_, recipe, _)| self.show.crafting_tab.satisfies(recipe.output.0.as_ref()))
|
||||
.enumerate()
|
||||
{
|
||||
let button = Button::image(
|
||||
@ -562,11 +511,11 @@ impl<'a> Widget for Crafting<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
//Ingredients
|
||||
if let Some(recipe) = state
|
||||
// Selected Recipe
|
||||
if let Some((recipe_name, recipe)) = state
|
||||
.selected_recipe
|
||||
.as_ref()
|
||||
.and_then(|r| self.client.recipe_book().get(r.as_str()))
|
||||
.and_then(|rn| self.client.recipe_book().get(rn.as_str()).map(|r| (rn, r)))
|
||||
{
|
||||
// Title
|
||||
Text::new(&recipe.output.0.name())
|
||||
@ -576,6 +525,132 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.title_ing, ui);
|
||||
let can_perform = self
|
||||
.client
|
||||
.available_recipes()
|
||||
.contains(recipe_name.as_str());
|
||||
|
||||
// Craft button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(105.0, 25.0)
|
||||
.hover_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_hover)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.press_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_press)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.label(&self.localized_strings.get("hud.crafting.craft"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR))
|
||||
.label_font_size(self.fonts.cyri.scale(12))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.image_color(can_perform.then_some(TEXT_COLOR).unwrap_or(TEXT_GRAY_COLOR))
|
||||
.mid_bottom_with_margin_on(state.ids.align_ing, -31.0)
|
||||
.parent(state.ids.window_frame)
|
||||
.set(state.ids.btn_craft, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::CraftRecipe(recipe_name.clone()));
|
||||
}
|
||||
|
||||
// Output Image Frame
|
||||
let quality_col_img = match recipe.output.0.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,
|
||||
};
|
||||
|
||||
Image::new(quality_col_img)
|
||||
.w_h(60.0, 60.0)
|
||||
.top_right_with_margins_on(state.ids.align_ing, 15.0, 10.0)
|
||||
.parent(state.ids.align_ing)
|
||||
.set(state.ids.output_img_frame, ui);
|
||||
|
||||
let output_text = format!("x{}", &recipe.output.1.to_string());
|
||||
// Output Image
|
||||
Button::image(animate_by_pulse(
|
||||
&self
|
||||
.item_imgs
|
||||
.img_ids_or_not_found_img((&*recipe.output.0).into()),
|
||||
self.pulse,
|
||||
))
|
||||
.w_h(55.0, 55.0)
|
||||
.label(&output_text)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(conrod_core::position::Relative::Scalar(-24.0))
|
||||
.label_x(conrod_core::position::Relative::Scalar(24.0))
|
||||
.middle_of(state.ids.output_img_frame)
|
||||
.with_item_tooltip(
|
||||
self.item_tooltip_manager,
|
||||
&*recipe.output.0,
|
||||
&None,
|
||||
&item_tooltip,
|
||||
)
|
||||
.set(state.ids.output_img, ui);
|
||||
|
||||
// Tags
|
||||
if state.ids.tags_ing.len() < CraftingTab::iter().len() {
|
||||
state.update(|state| {
|
||||
state
|
||||
.ids
|
||||
.tags_ing
|
||||
.resize(CraftingTab::iter().len(), &mut ui.widget_id_generator())
|
||||
});
|
||||
}
|
||||
for (row, chunk) in CraftingTab::iter()
|
||||
.filter(|crafting_tab| match crafting_tab {
|
||||
CraftingTab::All => false,
|
||||
_ => crafting_tab.satisfies(recipe.output.0.as_ref()),
|
||||
})
|
||||
.filter(|crafting_tab| crafting_tab != &self.show.crafting_tab)
|
||||
.collect::<Vec<_>>()
|
||||
.chunks(3)
|
||||
.enumerate()
|
||||
{
|
||||
for (col, crafting_tab) in chunk.iter().rev().enumerate() {
|
||||
let i = 3 * row + col;
|
||||
let icon = Image::new(crafting_tab.img_id(self.imgs))
|
||||
.w_h(20.0, 20.0)
|
||||
.parent(state.ids.window);
|
||||
let icon = if col == 0 {
|
||||
icon.bottom_right_with_margins_on(
|
||||
state.ids.output_img_frame,
|
||||
-24.0 - 24.0 * (row as f64),
|
||||
4.0,
|
||||
)
|
||||
} else {
|
||||
icon.left_from(state.ids.tags_ing[i - 1], 4.0)
|
||||
};
|
||||
icon.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&self.localized_strings.get(crafting_tab.name_key()),
|
||||
"",
|
||||
&tabs_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.tags_ing[i], ui);
|
||||
}
|
||||
}
|
||||
|
||||
// Ingredients Text
|
||||
Text::new(&self.localized_strings.get("hud.crafting.ingredients"))
|
||||
.top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.ingredients_txt, ui);
|
||||
|
||||
// Ingredient images with tooltip
|
||||
if state.ids.ingredient_frame.len() < recipe.inputs().len() {
|
||||
state.update(|state| {
|
||||
@ -725,6 +800,56 @@ impl<'a> Widget for Crafting<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search / Title Recipes
|
||||
if let Some(key) = &self.show.crafting_search_key {
|
||||
if Button::image(self.imgs.close_btn)
|
||||
.top_left_with_margins_on(state.ids.align_rec, -20.0, 5.0)
|
||||
.w_h(14.0, 14.0)
|
||||
.hover_image(self.imgs.close_btn_hover)
|
||||
.press_image(self.imgs.close_btn_press)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.btn_close_search, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::SearchRecipe(None));
|
||||
}
|
||||
if let Some(string) = TextEdit::new(key.as_str())
|
||||
.top_left_with_margins_on(state.ids.btn_close_search, -2.0, 18.0)
|
||||
.w_h(90.0, 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.input_search, ui)
|
||||
{
|
||||
events.push(Event::SearchRecipe(Some(string)));
|
||||
}
|
||||
} else {
|
||||
Text::new(&self.localized_strings.get("hud.crafting.recipes"))
|
||||
.mid_top_with_margin_on(state.ids.align_rec, -22.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.title_rec, ui);
|
||||
Rectangle::fill_with([114.0, 20.0], color::TRANSPARENT)
|
||||
.top_left_with_margins_on(state.ids.window, 52.0, 26.0)
|
||||
.graphics_for(state.ids.btn_open_search)
|
||||
.set(state.ids.input_overlay_search, ui);
|
||||
if Button::image(self.imgs.search_btn)
|
||||
.top_left_with_margins_on(state.ids.align_rec, -21.0, 5.0)
|
||||
.w_h(16.0, 16.0)
|
||||
.hover_image(self.imgs.search_btn_hover)
|
||||
.press_image(self.imgs.search_btn_press)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.btn_open_search, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::SearchRecipe(Some(String::new())));
|
||||
events.push(Event::Focus(state.ids.input_search));
|
||||
}
|
||||
}
|
||||
// Scrollbars
|
||||
Scrollbar::y_axis(state.ids.align_rec)
|
||||
.thickness(5.0)
|
||||
@ -735,15 +860,6 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.rgba(0.33, 0.33, 0.33, 1.0)
|
||||
.set(state.ids.scrollbar_ing, ui);
|
||||
|
||||
// Title Recipes and Ingredients
|
||||
Text::new(&self.localized_strings.get("hud.crafting.recipes"))
|
||||
.mid_top_with_margin_on(state.ids.align_rec, -22.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.parent(state.ids.window)
|
||||
.set(state.ids.title_rec, ui);
|
||||
|
||||
events
|
||||
}
|
||||
}
|
||||
|
@ -88,15 +88,6 @@ image_ids! {
|
||||
// Social Window
|
||||
social_frame_on: "voxygen.element.misc_bg.social_frame",
|
||||
social_bg_on: "voxygen.element.misc_bg.social_bg",
|
||||
social_frame_friends: "voxygen.element.misc_bg.social_frame",
|
||||
social_bg_friends: "voxygen.element.misc_bg.social_bg",
|
||||
social_frame_fact: "voxygen.element.misc_bg.social_frame",
|
||||
social_bg_fact: "voxygen.element.misc_bg.social_bg",
|
||||
social_tab_act: "voxygen.element.buttons.social_tab_active",
|
||||
social_tab_online: "voxygen.element.misc_bg.social_tab_online",
|
||||
social_tab_inact: "voxygen.element.buttons.social_tab_inactive",
|
||||
social_tab_inact_hover: "voxygen.element.buttons.social_tab_inactive",
|
||||
social_tab_inact_press: "voxygen.element.buttons.social_tab_inactive",
|
||||
|
||||
// Crafting Window
|
||||
crafting_window: "voxygen.element.misc_bg.crafting",
|
||||
@ -110,6 +101,7 @@ image_ids! {
|
||||
icon_dismantle: "voxygen.element.icons.dismantle",
|
||||
icon_food: "voxygen.element.icons.foods",
|
||||
icon_glider: "voxygen.element.icons.gliders",
|
||||
icon_globe: "voxygen.element.icons.globe",
|
||||
icon_potion: "voxygen.element.icons.potions",
|
||||
icon_utility: "voxygen.element.icons.utilities",
|
||||
icon_weapon: "voxygen.element.icons.weapons",
|
||||
@ -403,6 +395,10 @@ image_ids! {
|
||||
close_button_hover: "voxygen.element.buttons.close_btn_hover",
|
||||
close_button_press: "voxygen.element.buttons.close_btn_press",
|
||||
|
||||
// Search-button
|
||||
search_btn: "voxygen.element.buttons.search_btn",
|
||||
search_btn_hover: "voxygen.element.buttons.search_btn_hover",
|
||||
search_btn_press: "voxygen.element.buttons.search_btn_press",
|
||||
// Inventory
|
||||
collapse_btn: "voxygen.element.buttons.inv_collapse",
|
||||
collapse_btn_hover: "voxygen.element.buttons.inv_collapse_hover",
|
||||
|
@ -31,7 +31,7 @@ use buffs::BuffsBar;
|
||||
use buttons::Buttons;
|
||||
use chat::Chat;
|
||||
use chrono::NaiveTime;
|
||||
use crafting::{Crafting, SelectedCraftingTab};
|
||||
use crafting::{Crafting, CraftingTab};
|
||||
use diary::{Diary, SelectedSkillTree};
|
||||
use esc_menu::EscMenu;
|
||||
use group::Group;
|
||||
@ -44,7 +44,7 @@ use prompt_dialog::PromptDialog;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings_window::{SettingsTab, SettingsWindow};
|
||||
use skillbar::Skillbar;
|
||||
use social::{Social, SocialTab};
|
||||
use social::Social;
|
||||
use trade::Trade;
|
||||
|
||||
use crate::{
|
||||
@ -546,8 +546,9 @@ pub struct Show {
|
||||
ingame: bool,
|
||||
settings_tab: SettingsTab,
|
||||
skilltreetab: SelectedSkillTree,
|
||||
crafting_tab: SelectedCraftingTab,
|
||||
social_tab: SocialTab,
|
||||
crafting_tab: CraftingTab,
|
||||
crafting_search_key: Option<String>,
|
||||
social_search_key: Option<String>,
|
||||
want_grab: bool,
|
||||
stats: bool,
|
||||
free_look: bool,
|
||||
@ -561,6 +562,10 @@ impl Show {
|
||||
self.bag = open;
|
||||
self.map = false;
|
||||
self.want_grab = !open;
|
||||
|
||||
if !open {
|
||||
self.crafting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,6 +595,10 @@ impl Show {
|
||||
|
||||
fn social(&mut self, open: bool) {
|
||||
if !self.esc_menu {
|
||||
if !self.social && open {
|
||||
// rising edge detector
|
||||
self.search_social_players(None);
|
||||
}
|
||||
self.social = open;
|
||||
self.diary = false;
|
||||
self.want_grab = !open;
|
||||
@ -598,6 +607,10 @@ impl Show {
|
||||
|
||||
fn crafting(&mut self, open: bool) {
|
||||
if !self.esc_menu {
|
||||
if !self.crafting && open {
|
||||
// rising edge detector
|
||||
self.search_crafting_recipe(None);
|
||||
}
|
||||
self.crafting = open;
|
||||
self.bag = open;
|
||||
self.map = false;
|
||||
@ -711,11 +724,6 @@ impl Show {
|
||||
|
||||
fn toggle_crafting(&mut self) { self.crafting(!self.crafting) }
|
||||
|
||||
fn open_social_tab(&mut self, social_tab: SocialTab) {
|
||||
self.social_tab = social_tab;
|
||||
self.diary = false;
|
||||
}
|
||||
|
||||
fn toggle_spell(&mut self) {
|
||||
self.diary = !self.diary;
|
||||
self.bag = false;
|
||||
@ -730,8 +738,14 @@ impl Show {
|
||||
self.social = false;
|
||||
}
|
||||
|
||||
fn selected_crafting_tab(&mut self, sel_cat: SelectedCraftingTab) {
|
||||
self.crafting_tab = sel_cat;
|
||||
fn selected_crafting_tab(&mut self, sel_cat: CraftingTab) { self.crafting_tab = sel_cat; }
|
||||
|
||||
fn search_crafting_recipe(&mut self, search_key: Option<String>) {
|
||||
self.crafting_search_key = search_key;
|
||||
}
|
||||
|
||||
fn search_social_players(&mut self, search_key: Option<String>) {
|
||||
self.social_search_key = search_key;
|
||||
}
|
||||
|
||||
/// If all of the menus are closed, adjusts coordinates of cursor to center
|
||||
@ -890,8 +904,9 @@ impl Hud {
|
||||
group_menu: false,
|
||||
settings_tab: SettingsTab::Interface,
|
||||
skilltreetab: SelectedSkillTree::General,
|
||||
crafting_tab: SelectedCraftingTab::Armor,
|
||||
social_tab: SocialTab::Online,
|
||||
crafting_tab: CraftingTab::All,
|
||||
crafting_search_key: None,
|
||||
social_search_key: None,
|
||||
want_grab: true,
|
||||
ingame: true,
|
||||
stats: false,
|
||||
@ -2368,7 +2383,6 @@ impl Hud {
|
||||
Some(bag::Event::Close) => {
|
||||
self.show.stats = false;
|
||||
self.show.bag(false);
|
||||
self.show.crafting(false);
|
||||
if !self.show.social {
|
||||
self.show.want_grab = true;
|
||||
self.force_ungrab = false;
|
||||
@ -2469,7 +2483,6 @@ impl Hud {
|
||||
crafting::Event::Close => {
|
||||
self.show.stats = false;
|
||||
self.show.crafting(false);
|
||||
self.show.bag(false);
|
||||
if !self.show.social {
|
||||
self.show.want_grab = true;
|
||||
self.force_ungrab = false;
|
||||
@ -2480,6 +2493,12 @@ impl Hud {
|
||||
crafting::Event::ChangeCraftingTab(sel_cat) => {
|
||||
self.show.selected_crafting_tab(sel_cat);
|
||||
},
|
||||
crafting::Event::Focus(widget_id) => {
|
||||
self.to_focus = Some(Some(widget_id));
|
||||
},
|
||||
crafting::Event::SearchRecipe(search_key) => {
|
||||
self.show.search_crafting_recipe(search_key);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2735,10 +2754,13 @@ impl Hud {
|
||||
self.force_ungrab = true
|
||||
};
|
||||
},
|
||||
social::Event::ChangeSocialTab(social_tab) => {
|
||||
self.show.open_social_tab(social_tab)
|
||||
social::Event::Focus(widget_id) => {
|
||||
self.to_focus = Some(Some(widget_id));
|
||||
},
|
||||
social::Event::Invite(uid) => events.push(Event::InviteMember(uid)),
|
||||
social::Event::SearchPlayers(search_key) => {
|
||||
self.show.search_social_players(search_key)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use client::{self, Client};
|
||||
use common::{comp::group, uid::Uid};
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text, TextEdit},
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
@ -27,25 +27,14 @@ widget_ids! {
|
||||
icon,
|
||||
scrollbar,
|
||||
online_align,
|
||||
online_tab,
|
||||
names_align,
|
||||
name_txt,
|
||||
player_levels[],
|
||||
player_names[],
|
||||
player_zones[],
|
||||
online_txt,
|
||||
online_no,
|
||||
levels_align,
|
||||
level_txt,
|
||||
zones_align,
|
||||
zone_txt,
|
||||
friends_tab,
|
||||
//friends_tab_icon,
|
||||
faction_tab,
|
||||
//faction_tab_icon,
|
||||
friends_test,
|
||||
faction_test,
|
||||
invite_button,
|
||||
player_search_icon,
|
||||
player_search_input,
|
||||
player_search_input_bg,
|
||||
player_search_input_overlay,
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,12 +45,6 @@ pub struct State {
|
||||
selected_uid: Option<(Uid, Instant)>,
|
||||
}
|
||||
|
||||
pub enum SocialTab {
|
||||
Online,
|
||||
Friends,
|
||||
Faction,
|
||||
}
|
||||
|
||||
#[derive(WidgetCommon)]
|
||||
pub struct Social<'a> {
|
||||
show: &'a Show,
|
||||
@ -106,7 +89,8 @@ impl<'a> Social<'a> {
|
||||
pub enum Event {
|
||||
Close,
|
||||
Invite(Uid),
|
||||
ChangeSocialTab(SocialTab),
|
||||
Focus(widget::Id),
|
||||
SearchPlayers(Option<String>),
|
||||
}
|
||||
|
||||
impl<'a> Widget for Social<'a> {
|
||||
@ -145,33 +129,27 @@ impl<'a> Widget for Social<'a> {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.desc_text_color(TEXT_COLOR);
|
||||
|
||||
// Window frame and BG
|
||||
let pos = if self.show.group || self.show.group_menu {
|
||||
200.0
|
||||
} else {
|
||||
25.0
|
||||
};
|
||||
// TODO: Different window visuals depending on the selected tab
|
||||
let window_bg = match &self.show.social_tab {
|
||||
SocialTab::Online => self.imgs.social_bg_on,
|
||||
SocialTab::Friends => self.imgs.social_bg_friends,
|
||||
SocialTab::Faction => self.imgs.social_bg_fact,
|
||||
};
|
||||
let window_frame = match &self.show.social_tab {
|
||||
SocialTab::Online => self.imgs.social_frame_on,
|
||||
SocialTab::Friends => self.imgs.social_frame_friends,
|
||||
SocialTab::Faction => self.imgs.social_frame_fact,
|
||||
};
|
||||
Image::new(window_bg)
|
||||
.bottom_left_with_margins_on(ui.window, 308.0, pos)
|
||||
// Window BG
|
||||
Image::new(self.imgs.social_bg_on)
|
||||
.bottom_left_with_margins_on(ui.window, 308.0, 25.0)
|
||||
.color(Some(UI_MAIN))
|
||||
.w_h(280.0, 460.0)
|
||||
.set(state.ids.bg, ui);
|
||||
Image::new(window_frame)
|
||||
// Search Background
|
||||
// I couldn't find a way to manually set they layer of a widget
|
||||
// If it is possible, please move this code (for rectangle) down to the code for
|
||||
// search input
|
||||
Rectangle::fill([248.0, 20.0])
|
||||
.top_left_with_margins_on(state.ids.bg, 52.0, 27.0)
|
||||
.hsla(0.0, 0.0, 0.0, 0.7)
|
||||
.set(state.ids.player_search_input_bg, ui);
|
||||
// Window frame
|
||||
Image::new(self.imgs.social_frame_on)
|
||||
.middle_of(state.ids.bg)
|
||||
.color(Some(UI_HIGHLIGHT_0))
|
||||
.w_h(280.0, 460.0)
|
||||
.set(state.ids.frame, ui);
|
||||
|
||||
// Icon
|
||||
Image::new(self.imgs.social)
|
||||
.w_h(30.0, 30.0)
|
||||
@ -200,381 +178,269 @@ impl<'a> Widget for Social<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.title, ui);
|
||||
|
||||
// Tabs Buttons
|
||||
// Online Tab Button
|
||||
if Button::image(match &self.show.social_tab {
|
||||
SocialTab::Online => self.imgs.social_tab_online,
|
||||
_ => self.imgs.social_tab_inact,
|
||||
})
|
||||
.w_h(30.0, 44.0)
|
||||
.image_color(match &self.show.social_tab {
|
||||
SocialTab::Online => UI_MAIN,
|
||||
_ => Color::Rgba(1.0, 1.0, 1.0, 0.6),
|
||||
})
|
||||
.top_right_with_margins_on(state.ids.frame, 50.0, -27.0)
|
||||
.set(state.ids.online_tab, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeSocialTab(SocialTab::Online));
|
||||
}
|
||||
// Friends Tab Button
|
||||
if Button::image(match &self.show.social_tab {
|
||||
SocialTab::Friends => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact,
|
||||
})
|
||||
.w_h(30.0, 44.0)
|
||||
.hover_image(match &self.show.social_tab {
|
||||
SocialTab::Friends => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact_hover,
|
||||
})
|
||||
.press_image(match &self.show.social_tab {
|
||||
SocialTab::Friends => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact_press,
|
||||
})
|
||||
.down_from(state.ids.online_tab, 0.0)
|
||||
.image_color(match &self.show.social_tab {
|
||||
SocialTab::Friends => UI_MAIN,
|
||||
_ => Color::Rgba(1.0, 1.0, 1.0, 0.6),
|
||||
})
|
||||
.set(state.ids.friends_tab, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeSocialTab(SocialTab::Friends));
|
||||
}
|
||||
// Faction Tab Button
|
||||
if Button::image(match &self.show.social_tab {
|
||||
SocialTab::Friends => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact,
|
||||
})
|
||||
.w_h(30.0, 44.0)
|
||||
.hover_image(match &self.show.social_tab {
|
||||
SocialTab::Faction => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact_hover,
|
||||
})
|
||||
.press_image(match &self.show.social_tab {
|
||||
SocialTab::Faction => self.imgs.social_tab_act,
|
||||
_ => self.imgs.social_tab_inact_press,
|
||||
})
|
||||
.down_from(state.ids.friends_tab, 0.0)
|
||||
.image_color(match &self.show.social_tab {
|
||||
SocialTab::Faction => UI_MAIN,
|
||||
_ => Color::Rgba(1.0, 1.0, 1.0, 0.6),
|
||||
})
|
||||
.set(state.ids.faction_tab, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeSocialTab(SocialTab::Faction));
|
||||
}
|
||||
// Online Tab
|
||||
if let SocialTab::Online = self.show.social_tab {
|
||||
let players = self
|
||||
.client
|
||||
.player_list()
|
||||
.iter()
|
||||
.filter(|(_, p)| p.is_online);
|
||||
let count = players.clone().count();
|
||||
let height = if count > 1 {
|
||||
count as f64 - 1.0 + 20.0 * count as f64 - 1.0
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
// Content Alignments
|
||||
Rectangle::fill_with([270.0, 346.0], color::TRANSPARENT)
|
||||
.mid_top_with_margin_on(state.ids.frame, 74.0)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.online_align, ui);
|
||||
Rectangle::fill_with([133.0, height], color::TRANSPARENT)
|
||||
.top_left_with_margins_on(state.ids.online_align, 0.0, 0.0)
|
||||
.crop_kids()
|
||||
.set(state.ids.names_align, ui);
|
||||
Rectangle::fill_with([39.0, height], color::TRANSPARENT)
|
||||
.right_from(state.ids.names_align, 2.0)
|
||||
.crop_kids()
|
||||
.set(state.ids.levels_align, ui);
|
||||
Rectangle::fill_with([94.0, height], color::TRANSPARENT)
|
||||
.right_from(state.ids.levels_align, 2.0)
|
||||
.crop_kids()
|
||||
.set(state.ids.zones_align, ui);
|
||||
Scrollbar::y_axis(state.ids.online_align)
|
||||
.thickness(4.0)
|
||||
.color(Color::Rgba(0.79, 1.09, 1.09, 0.0))
|
||||
.set(state.ids.scrollbar, ui);
|
||||
//
|
||||
// Headlines
|
||||
//
|
||||
if Button::image(self.imgs.nothing)
|
||||
.w_h(133.0, 18.0)
|
||||
.mid_top_with_margin_on(state.ids.frame, 52.0)
|
||||
.label(&self.localized_strings.get(""))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(conrod_core::position::Relative::Scalar(0.0))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.name_txt, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
// Sort widgets by name alphabetically
|
||||
}
|
||||
if Button::image(self.imgs.nothing)
|
||||
.w_h(39.0, 18.0)
|
||||
.right_from(state.ids.name_txt, 2.0)
|
||||
.label("")
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(conrod_core::position::Relative::Scalar(0.0))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.level_txt, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
// Sort widgets by level (increasing)
|
||||
}
|
||||
if Button::image(self.imgs.nothing)
|
||||
.w_h(93.0, 18.0)
|
||||
.right_from(state.ids.level_txt, 2.0)
|
||||
.label("") // TODO: Enable zone here later
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(conrod_core::position::Relative::Scalar(0.0))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.zone_txt, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
// Sort widgets by zone alphabetically
|
||||
}
|
||||
// Online Text
|
||||
Text::new(&self.localized_strings.get("hud.social.online"))
|
||||
.bottom_left_with_margins_on(state.ids.frame, 18.0, 10.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.online_txt, ui);
|
||||
Text::new(&count.to_string())
|
||||
.right_from(state.ids.online_txt, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.online_no, ui);
|
||||
// Adjust widget_id struct vec length to player count
|
||||
if state.ids.player_levels.len() < count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_levels
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
})
|
||||
};
|
||||
if state.ids.player_names.len() < count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_names
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
})
|
||||
};
|
||||
if state.ids.player_zones.len() < count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_zones
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
})
|
||||
};
|
||||
// Create a name, level and zone row for every player in the list
|
||||
// Filter out yourself from the online list
|
||||
let my_uid = self.client.uid();
|
||||
let mut player_list = players
|
||||
.filter(|(uid, _)| Some(**uid) != my_uid)
|
||||
.collect_vec();
|
||||
player_list.sort_by_key(|(_, player)| {
|
||||
player
|
||||
.character
|
||||
let players = self
|
||||
.client
|
||||
.player_list()
|
||||
.iter()
|
||||
.filter(|(_, p)| p.is_online);
|
||||
let player_count = players.clone().count();
|
||||
|
||||
// Content Alignment
|
||||
Rectangle::fill_with([270.0, 346.0], color::TRANSPARENT)
|
||||
.mid_top_with_margin_on(state.ids.frame, 74.0)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.online_align, ui);
|
||||
Scrollbar::y_axis(state.ids.online_align)
|
||||
.thickness(4.0)
|
||||
.color(Color::Rgba(0.79, 1.09, 1.09, 0.0))
|
||||
.set(state.ids.scrollbar, ui);
|
||||
|
||||
// Online Text
|
||||
Text::new(&self.localized_strings.get("hud.social.online"))
|
||||
.bottom_left_with_margins_on(state.ids.frame, 18.0, 10.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.online_txt, ui);
|
||||
Text::new(&player_count.to_string())
|
||||
.right_from(state.ids.online_txt, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.online_no, ui);
|
||||
// Adjust widget_id struct vec length to player count
|
||||
if state.ids.player_names.len() < player_count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_names
|
||||
.resize(player_count, &mut ui.widget_id_generator())
|
||||
})
|
||||
};
|
||||
|
||||
// Filter out yourself from the online list and perform search
|
||||
let my_uid = self.client.uid();
|
||||
let mut player_list = players
|
||||
.filter(|(uid, _)| Some(**uid) != my_uid)
|
||||
.filter(|(_, player)| {
|
||||
self.show
|
||||
.social_search_key
|
||||
.as_ref()
|
||||
.map(|character| character.name.to_lowercase())
|
||||
.unwrap_or_else(|| player.player_alias.to_string())
|
||||
});
|
||||
for (i, (&uid, player_info)) in player_list.into_iter().enumerate() {
|
||||
let hide_username = true;
|
||||
let zone = ""; // TODO Add real zone
|
||||
let selected = state.selected_uid.map_or(false, |u| u.0 == uid);
|
||||
let alias = &player_info.player_alias;
|
||||
let zone_name = match &player_info.character {
|
||||
None => self.localized_strings.get("hud.group.in_menu").to_string(), /* character select or spectating */
|
||||
_ => format!("{} ", &zone),
|
||||
};
|
||||
let name_text = match &player_info.character {
|
||||
Some(character) => {
|
||||
if hide_username {
|
||||
character.name.to_string()
|
||||
} else {
|
||||
format!("[{}] {}", alias, &character.name)
|
||||
}
|
||||
},
|
||||
None => format!("{} [{}]", alias.clone(), zone_name), /* character select or
|
||||
* spectating */
|
||||
};
|
||||
// Player name widgets
|
||||
let button = Button::image(if !selected {
|
||||
self.imgs.nothing
|
||||
} else {
|
||||
self.imgs.selection
|
||||
});
|
||||
let button = if i == 0 {
|
||||
button.mid_top_with_margin_on(state.ids.online_align, 1.0)
|
||||
} else {
|
||||
button.down_from(state.ids.player_names[i - 1], 1.0)
|
||||
};
|
||||
let acc_name_txt = format!(
|
||||
"{}: {}",
|
||||
&self.localized_strings.get("hud.social.account"),
|
||||
alias
|
||||
);
|
||||
button
|
||||
.w_h(260.0, 20.0)
|
||||
.hover_image(if selected {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.selection_hover
|
||||
.map(|search_key| {
|
||||
search_key
|
||||
.to_lowercase()
|
||||
.split_whitespace()
|
||||
.all(|substring| {
|
||||
let player_alias = &player.player_alias.to_lowercase();
|
||||
let character_name = player
|
||||
.character
|
||||
.as_ref()
|
||||
.map(|character| character.name.to_lowercase());
|
||||
player_alias.contains(substring)
|
||||
|| character_name
|
||||
.map(|cn| cn.contains(substring))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
})
|
||||
.press_image(if selected {
|
||||
self.imgs.selection
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.collect_vec();
|
||||
player_list.sort_by_key(|(_, player)| {
|
||||
player
|
||||
.character
|
||||
.as_ref()
|
||||
.map(|character| &character.name)
|
||||
.unwrap_or(&player.player_alias)
|
||||
.to_lowercase()
|
||||
});
|
||||
for (i, (&uid, player_info)) in player_list.into_iter().enumerate() {
|
||||
let hide_username = true;
|
||||
let selected = state.selected_uid.map_or(false, |u| u.0 == uid);
|
||||
let alias = &player_info.player_alias;
|
||||
let name_text = match &player_info.character {
|
||||
Some(character) => {
|
||||
if hide_username {
|
||||
character.name.to_string()
|
||||
} else {
|
||||
self.imgs.selection_press
|
||||
})
|
||||
.label(&name_text)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&acc_name_txt,
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.player_names[i], ui);
|
||||
// Player Zones
|
||||
Button::image(if !selected {
|
||||
self.imgs.nothing
|
||||
} else {
|
||||
self.imgs.selection
|
||||
})
|
||||
.w_h(94.0, 20.0)
|
||||
.right_from(state.ids.player_levels[i], 2.0)
|
||||
.label(&zone_name)
|
||||
format!("[{}] {}", alias, &character.name)
|
||||
}
|
||||
},
|
||||
None => format!(
|
||||
"{} [{}]",
|
||||
alias.clone(),
|
||||
self.localized_strings.get("hud.group.in_menu").to_string()
|
||||
), // character select or spectating
|
||||
};
|
||||
let acc_name_txt = format!(
|
||||
"{}: {}",
|
||||
&self.localized_strings.get("hud.social.account"),
|
||||
alias
|
||||
);
|
||||
// Player name widget
|
||||
let button = Button::image(if !selected {
|
||||
self.imgs.nothing
|
||||
} else {
|
||||
self.imgs.selection
|
||||
})
|
||||
.hover_image(if selected {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.selection_hover
|
||||
})
|
||||
.press_image(if selected {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.selection_press
|
||||
})
|
||||
.w_h(260.0, 20.0);
|
||||
let button = if i == 0 {
|
||||
button.mid_top_with_margin_on(state.ids.online_align, 1.0)
|
||||
} else {
|
||||
button.down_from(state.ids.player_names[i - 1], 1.0)
|
||||
};
|
||||
if button
|
||||
.label(&name_text)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.parent(state.ids.zones_align)
|
||||
.set(state.ids.player_zones[i], ui);
|
||||
// Check for click
|
||||
if ui
|
||||
.widget_input(state.ids.player_names[i])
|
||||
.clicks()
|
||||
.left()
|
||||
.next()
|
||||
.is_some()
|
||||
{
|
||||
state.update(|s| s.selected_uid = Some((uid, Instant::now())));
|
||||
}
|
||||
}
|
||||
|
||||
// Invite Button
|
||||
let is_leader_or_not_in_group = self
|
||||
.client
|
||||
.group_info()
|
||||
.map_or(true, |(_, l_uid)| self.client.uid() == Some(l_uid));
|
||||
|
||||
let current_members = self
|
||||
.client
|
||||
.group_members()
|
||||
.iter()
|
||||
.filter(|(_, role)| matches!(role, group::Role::Member))
|
||||
.count()
|
||||
+ 1;
|
||||
let current_invites = self.client.pending_invites().len();
|
||||
let max_members = self.client.max_group_size() as usize;
|
||||
let group_not_full = current_members + current_invites < max_members;
|
||||
let selected_to_invite = (is_leader_or_not_in_group && group_not_full)
|
||||
.then(|| {
|
||||
state
|
||||
.selected_uid
|
||||
.as_ref()
|
||||
.map(|(s, _)| *s)
|
||||
.filter(|selected| {
|
||||
self.client.player_list().get(selected).map_or(
|
||||
false,
|
||||
|selected_player| {
|
||||
selected_player.is_online && selected_player.character.is_some()
|
||||
},
|
||||
)
|
||||
})
|
||||
.or_else(|| {
|
||||
self.selected_entity
|
||||
.and_then(|s| self.client.state().read_component_copied(s.0))
|
||||
})
|
||||
.filter(|selected| {
|
||||
// Prevent inviting entities already in the same group
|
||||
!self.client.group_members().contains_key(selected)
|
||||
})
|
||||
})
|
||||
.flatten();
|
||||
|
||||
let invite_button = Button::image(self.imgs.button)
|
||||
.w_h(106.0, 26.0)
|
||||
.bottom_right_with_margins_on(state.ids.frame, 9.0, 7.0)
|
||||
.hover_image(if selected_to_invite.is_some() {
|
||||
self.imgs.button_hover
|
||||
} else {
|
||||
self.imgs.button
|
||||
})
|
||||
.press_image(if selected_to_invite.is_some() {
|
||||
self.imgs.button_press
|
||||
} else {
|
||||
self.imgs.button
|
||||
})
|
||||
.label(self.localized_strings.get("hud.group.invite"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(if selected_to_invite.is_some() {
|
||||
TEXT_COLOR
|
||||
} else {
|
||||
TEXT_COLOR_3
|
||||
})
|
||||
.image_color(if selected_to_invite.is_some() {
|
||||
TEXT_COLOR
|
||||
} else {
|
||||
TEXT_COLOR_3
|
||||
})
|
||||
.label_font_size(self.fonts.cyri.scale(15))
|
||||
.label_font_id(self.fonts.cyri.conrod_id);
|
||||
|
||||
if if self.client.group_info().is_some() {
|
||||
let tooltip_txt = format!(
|
||||
"{}/{} {}",
|
||||
current_members + current_invites,
|
||||
max_members,
|
||||
&self.localized_strings.get("hud.group.members")
|
||||
);
|
||||
invite_button
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&tooltip_txt,
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.invite_button, ui)
|
||||
} else {
|
||||
invite_button.set(state.ids.invite_button, ui)
|
||||
}
|
||||
.was_clicked()
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&acc_name_txt,
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.player_names[i], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
if let Some(uid) = selected_to_invite {
|
||||
events.push(Event::Invite(uid));
|
||||
state.update(|s| {
|
||||
s.selected_uid = None;
|
||||
});
|
||||
}
|
||||
state.update(|s| s.selected_uid = Some((uid, Instant::now())));
|
||||
}
|
||||
} // End of Online Tab
|
||||
}
|
||||
|
||||
// Invite Button
|
||||
let is_leader_or_not_in_group = self
|
||||
.client
|
||||
.group_info()
|
||||
.map_or(true, |(_, l_uid)| self.client.uid() == Some(l_uid));
|
||||
|
||||
let current_members = self
|
||||
.client
|
||||
.group_members()
|
||||
.iter()
|
||||
.filter(|(_, role)| matches!(role, group::Role::Member))
|
||||
.count()
|
||||
+ 1;
|
||||
let current_invites = self.client.pending_invites().len();
|
||||
let max_members = self.client.max_group_size() as usize;
|
||||
let group_not_full = current_members + current_invites < max_members;
|
||||
let selected_to_invite = (is_leader_or_not_in_group && group_not_full)
|
||||
.then(|| {
|
||||
state
|
||||
.selected_uid
|
||||
.as_ref()
|
||||
.map(|(s, _)| *s)
|
||||
.filter(|selected| {
|
||||
self.client
|
||||
.player_list()
|
||||
.get(selected)
|
||||
.map_or(false, |selected_player| {
|
||||
selected_player.is_online && selected_player.character.is_some()
|
||||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
self.selected_entity
|
||||
.and_then(|s| self.client.state().read_component_copied(s.0))
|
||||
})
|
||||
.filter(|selected| {
|
||||
// Prevent inviting entities already in the same group
|
||||
!self.client.group_members().contains_key(selected)
|
||||
})
|
||||
})
|
||||
.flatten();
|
||||
|
||||
let invite_button = Button::image(self.imgs.button)
|
||||
.w_h(106.0, 26.0)
|
||||
.bottom_right_with_margins_on(state.ids.frame, 9.0, 7.0)
|
||||
.hover_image(if selected_to_invite.is_some() {
|
||||
self.imgs.button_hover
|
||||
} else {
|
||||
self.imgs.button
|
||||
})
|
||||
.press_image(if selected_to_invite.is_some() {
|
||||
self.imgs.button_press
|
||||
} else {
|
||||
self.imgs.button
|
||||
})
|
||||
.label(self.localized_strings.get("hud.group.invite"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(if selected_to_invite.is_some() {
|
||||
TEXT_COLOR
|
||||
} else {
|
||||
TEXT_COLOR_3
|
||||
})
|
||||
.image_color(if selected_to_invite.is_some() {
|
||||
TEXT_COLOR
|
||||
} else {
|
||||
TEXT_COLOR_3
|
||||
})
|
||||
.label_font_size(self.fonts.cyri.scale(15))
|
||||
.label_font_id(self.fonts.cyri.conrod_id);
|
||||
|
||||
if if self.client.group_info().is_some() {
|
||||
let tooltip_txt = format!(
|
||||
"{}/{} {}",
|
||||
current_members + current_invites,
|
||||
max_members,
|
||||
&self.localized_strings.get("hud.group.members")
|
||||
);
|
||||
invite_button
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&tooltip_txt,
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.invite_button, ui)
|
||||
} else {
|
||||
invite_button.set(state.ids.invite_button, ui)
|
||||
}
|
||||
.was_clicked()
|
||||
{
|
||||
if let Some(uid) = selected_to_invite {
|
||||
events.push(Event::Invite(uid));
|
||||
state.update(|s| {
|
||||
s.selected_uid = None;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Player Search
|
||||
if Button::image(self.imgs.search_btn)
|
||||
.top_left_with_margins_on(state.ids.frame, 54.0, 9.0)
|
||||
.hover_image(self.imgs.search_btn_hover)
|
||||
.press_image(self.imgs.search_btn_press)
|
||||
.w_h(16.0, 16.0)
|
||||
.set(state.ids.player_search_icon, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::Focus(state.ids.player_search_input));
|
||||
}
|
||||
if let Some(string) =
|
||||
TextEdit::new(self.show.social_search_key.as_deref().unwrap_or_default())
|
||||
.top_left_with_margins_on(state.ids.player_search_icon, -1.0, 22.0)
|
||||
.w_h(215.0, 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.player_search_input, ui)
|
||||
{
|
||||
events.push(Event::SearchPlayers(Some(string)));
|
||||
}
|
||||
Rectangle::fill_with([266.0, 20.0], color::TRANSPARENT)
|
||||
.top_left_with_margins_on(state.ids.player_search_icon, -1.0, 0.0)
|
||||
.graphics_for(state.ids.player_search_icon)
|
||||
.set(state.ids.player_search_input_overlay, ui);
|
||||
|
||||
events
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user