mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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
This commit is contained in:
parent
60efd682e2
commit
be42cc60c4
@ -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,20 +266,35 @@ 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
|
||||
if Button::image(self.imgs.close_button)
|
||||
.w_h(24.0, 25.0)
|
||||
@ -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,147 +178,23 @@ 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
|
||||
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);
|
||||
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)
|
||||
@ -348,56 +202,60 @@ impl<'a> Widget for Social<'a> {
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.online_txt, ui);
|
||||
Text::new(&count.to_string())
|
||||
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_levels.len() < count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_levels
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
})
|
||||
};
|
||||
if state.ids.player_names.len() < count {
|
||||
if state.ids.player_names.len() < player_count {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.player_names
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
.resize(player_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
|
||||
|
||||
// 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(|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)
|
||||
})
|
||||
})
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.collect_vec();
|
||||
player_list.sort_by_key(|(_, player)| {
|
||||
player
|
||||
.character
|
||||
.as_ref()
|
||||
.map(|character| character.name.to_lowercase())
|
||||
.unwrap_or_else(|| player.player_alias.to_string())
|
||||
.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 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 {
|
||||
@ -406,27 +264,23 @@ impl<'a> Widget for Social<'a> {
|
||||
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)
|
||||
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
|
||||
);
|
||||
button
|
||||
.w_h(260.0, 20.0)
|
||||
// Player name widget
|
||||
let button = Button::image(if !selected {
|
||||
self.imgs.nothing
|
||||
} else {
|
||||
self.imgs.selection
|
||||
})
|
||||
.hover_image(if selected {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
@ -437,6 +291,13 @@ impl<'a> Widget for Social<'a> {
|
||||
} 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))
|
||||
@ -449,29 +310,8 @@ impl<'a> Widget for Social<'a> {
|
||||
&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)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.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()
|
||||
.set(state.ids.player_names[i], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
state.update(|s| s.selected_uid = Some((uid, Instant::now())));
|
||||
}
|
||||
@ -500,12 +340,12 @@ impl<'a> Widget for Social<'a> {
|
||||
.as_ref()
|
||||
.map(|(s, _)| *s)
|
||||
.filter(|selected| {
|
||||
self.client.player_list().get(selected).map_or(
|
||||
false,
|
||||
|selected_player| {
|
||||
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
|
||||
@ -574,7 +414,33 @@ impl<'a> Widget for Social<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
} // End of Online Tab
|
||||
|
||||
// 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