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
|
- Crafting menu tabs
|
||||||
- Auto camera setting, making the game easier to play with one hand
|
- Auto camera setting, making the game easier to play with one hand
|
||||||
- Topographic map option
|
- Topographic map option
|
||||||
|
- Search bars for social and crafting window
|
||||||
|
|
||||||
### Changed
|
### 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
|
- Added a raycast check to beams to prevent their effect applying through walls
|
||||||
- Flying agents raycast more angles to check for obstacles.
|
- Flying agents raycast more angles to check for obstacles.
|
||||||
- Mouse Cursor now locks to the center of the screen when menu is not open
|
- 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
|
## [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.ingredients": "Ingredients:",
|
||||||
"hud.crafting.craft": "Craft",
|
"hud.crafting.craft": "Craft",
|
||||||
"hud.crafting.tool_cata": "Requires:",
|
"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,
|
recipe::RecipeInput,
|
||||||
};
|
};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color, image,
|
||||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
widget::{self, Button, Image, Rectangle, Scrollbar, Text, TextEdit},
|
||||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -41,7 +41,13 @@ widget_ids! {
|
|||||||
title_rec,
|
title_rec,
|
||||||
align_rec,
|
align_rec,
|
||||||
scrollbar_rec,
|
scrollbar_rec,
|
||||||
|
btn_open_search,
|
||||||
|
btn_close_search,
|
||||||
|
input_search,
|
||||||
|
input_bg_search,
|
||||||
|
input_overlay_search,
|
||||||
title_ing,
|
title_ing,
|
||||||
|
tags_ing[],
|
||||||
align_ing,
|
align_ing,
|
||||||
scrollbar_ing,
|
scrollbar_ing,
|
||||||
btn_craft,
|
btn_craft,
|
||||||
@ -64,8 +70,10 @@ widget_ids! {
|
|||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
CraftRecipe(String),
|
CraftRecipe(String),
|
||||||
ChangeCraftingTab(SelectedCraftingTab),
|
ChangeCraftingTab(CraftingTab),
|
||||||
Close,
|
Close,
|
||||||
|
Focus(widget::Id),
|
||||||
|
SearchRecipe(Option<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
@ -120,7 +128,8 @@ impl<'a> Crafting<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, EnumIter, PartialEq)]
|
#[derive(Debug, EnumIter, PartialEq)]
|
||||||
pub enum SelectedCraftingTab {
|
pub enum CraftingTab {
|
||||||
|
All,
|
||||||
Armor,
|
Armor,
|
||||||
Weapon,
|
Weapon,
|
||||||
Food,
|
Food,
|
||||||
@ -131,6 +140,61 @@ pub enum SelectedCraftingTab {
|
|||||||
Utility,
|
Utility,
|
||||||
Glider,
|
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 {
|
pub struct State {
|
||||||
ids: Ids,
|
ids: Ids,
|
||||||
@ -155,15 +219,6 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
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();
|
let mut events = Vec::new();
|
||||||
|
|
||||||
// Tooltips
|
// Tooltips
|
||||||
@ -211,21 +266,36 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.desc_text_color(TEXT_COLOR);
|
.desc_text_color(TEXT_COLOR);
|
||||||
|
|
||||||
|
// Frame and window
|
||||||
Image::new(self.imgs.crafting_window)
|
Image::new(self.imgs.crafting_window)
|
||||||
.bottom_right_with_margins_on(ui.window, 308.0, 450.0)
|
.bottom_right_with_margins_on(ui.window, 308.0, 450.0)
|
||||||
.color(Some(UI_MAIN))
|
.color(Some(UI_MAIN))
|
||||||
.w_h(422.0, 460.0)
|
.w_h(422.0, 460.0)
|
||||||
.set(state.ids.window, ui);
|
.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)
|
Image::new(self.imgs.crafting_frame)
|
||||||
.middle_of(state.ids.window)
|
.middle_of(state.ids.window)
|
||||||
.color(Some(UI_HIGHLIGHT_0))
|
.color(Some(UI_HIGHLIGHT_0))
|
||||||
.w_h(422.0, 460.0)
|
.w_h(422.0, 460.0)
|
||||||
.set(state.ids.window_frame, ui);
|
.set(state.ids.window_frame, ui);
|
||||||
|
|
||||||
|
// Crafting Icon
|
||||||
Image::new(self.imgs.crafting_icon_bordered)
|
Image::new(self.imgs.crafting_icon_bordered)
|
||||||
.w_h(38.0, 38.0)
|
.w_h(38.0, 38.0)
|
||||||
.top_left_with_margins_on(state.ids.window_frame, 4.0, 4.0)
|
.top_left_with_margins_on(state.ids.window_frame, 4.0, 4.0)
|
||||||
.set(state.ids.icon, ui);
|
.set(state.ids.icon, ui);
|
||||||
// Close Button
|
|
||||||
|
// Close Button
|
||||||
if Button::image(self.imgs.close_button)
|
if Button::image(self.imgs.close_button)
|
||||||
.w_h(24.0, 25.0)
|
.w_h(24.0, 25.0)
|
||||||
.hover_image(self.imgs.close_button_hover)
|
.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)
|
.top_right_with_margins_on(state.ids.window, 74.0, 5.0)
|
||||||
.scroll_kids_vertically()
|
.scroll_kids_vertically()
|
||||||
.set(state.ids.align_ing, ui);
|
.set(state.ids.align_ing, ui);
|
||||||
|
|
||||||
// Category Tabs
|
// 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| {
|
state.update(|s| {
|
||||||
s.ids.category_bgs.resize(
|
s.ids.category_bgs.resize(
|
||||||
SelectedCraftingTab::iter().enumerate().len(),
|
CraftingTab::iter().enumerate().len(),
|
||||||
&mut ui.widget_id_generator(),
|
&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| {
|
state.update(|s| {
|
||||||
s.ids.category_tabs.resize(
|
s.ids.category_tabs.resize(
|
||||||
SelectedCraftingTab::iter().enumerate().len(),
|
CraftingTab::iter().enumerate().len(),
|
||||||
&mut ui.widget_id_generator(),
|
&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| {
|
state.update(|s| {
|
||||||
s.ids.category_imgs.resize(
|
s.ids.category_imgs.resize(
|
||||||
SelectedCraftingTab::iter().enumerate().len(),
|
CraftingTab::iter().enumerate().len(),
|
||||||
&mut ui.widget_id_generator(),
|
&mut ui.widget_id_generator(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let sel_crafting_tab = &self.show.crafting_tab;
|
let sel_crafting_tab = &self.show.crafting_tab;
|
||||||
for i in SelectedCraftingTab::iter().enumerate() {
|
for (i, crafting_tab) in CraftingTab::iter().enumerate() {
|
||||||
// TODO: i18n!
|
let tab_img = crafting_tab.img_id(self.imgs);
|
||||||
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,
|
|
||||||
};
|
|
||||||
// Button Background
|
// Button Background
|
||||||
let mut bg = Image::new(self.imgs.pixel)
|
let mut bg = Image::new(self.imgs.pixel)
|
||||||
.w_h(40.0, 30.0)
|
.w_h(40.0, 30.0)
|
||||||
.color(Some(UI_MAIN));
|
.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)
|
bg = bg.top_left_with_margins_on(state.ids.window_frame, 50.0, -40.0)
|
||||||
} else {
|
} 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
|
// 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
|
self.imgs.wpn_icon_border_pressed
|
||||||
} else {
|
} else {
|
||||||
self.imgs.wpn_icon_border
|
self.imgs.wpn_icon_border
|
||||||
})
|
})
|
||||||
.wh_of(state.ids.category_bgs[i.0])
|
.wh_of(state.ids.category_bgs[i])
|
||||||
.middle_of(state.ids.category_bgs[i.0])
|
.middle_of(state.ids.category_bgs[i])
|
||||||
.hover_image(if i.1 == *sel_crafting_tab {
|
.hover_image(if crafting_tab == *sel_crafting_tab {
|
||||||
self.imgs.wpn_icon_border_pressed
|
self.imgs.wpn_icon_border_pressed
|
||||||
} else {
|
} else {
|
||||||
self.imgs.wpn_icon_border_mo
|
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
|
self.imgs.wpn_icon_border_pressed
|
||||||
} else {
|
} else {
|
||||||
self.imgs.wpn_icon_border_press
|
self.imgs.wpn_icon_border_press
|
||||||
})
|
})
|
||||||
.with_tooltip(
|
.with_tooltip(
|
||||||
self.tooltip_manager,
|
self.tooltip_manager,
|
||||||
tab_name,
|
&self.localized_strings.get(crafting_tab.name_key()),
|
||||||
"",
|
"",
|
||||||
&tabs_tooltip,
|
&tabs_tooltip,
|
||||||
TEXT_COLOR,
|
TEXT_COLOR,
|
||||||
)
|
)
|
||||||
.set(state.ids.category_tabs[i.0], ui)
|
.set(state.ids.category_tabs[i], ui)
|
||||||
.was_clicked()
|
.was_clicked()
|
||||||
{
|
{
|
||||||
events.push(Event::ChangeCraftingTab(i.1))
|
events.push(Event::ChangeCraftingTab(crafting_tab))
|
||||||
};
|
};
|
||||||
// Tab images
|
// Tab images
|
||||||
Image::new(tab_img)
|
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)
|
.w_h(20.0, 20.0)
|
||||||
.graphics_for(state.ids.category_tabs[i.0])
|
.graphics_for(state.ids.category_tabs[i])
|
||||||
.set(state.ids.category_imgs[i.0], ui);
|
.set(state.ids.category_imgs[i], ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = &self.client;
|
|
||||||
// First available recipes, then unavailable ones, each alphabetically
|
// First available recipes, then unavailable ones, each alphabetically
|
||||||
// In the triples, "name" is the recipe book key, and "recipe.output.0.name()"
|
// In the triples, "name" is the recipe book key, and "recipe.output.0.name()"
|
||||||
// is the display name (as stored in the item descriptors)
|
// is the display name (as stored in the item descriptors)
|
||||||
@ -366,6 +414,17 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.client
|
.client
|
||||||
.recipe_book()
|
.recipe_book()
|
||||||
.iter()
|
.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)| {
|
.map(|(name, recipe)| {
|
||||||
let at_least_some_ingredients = recipe.inputs.iter().any(|(input, amount)| {
|
let at_least_some_ingredients = recipe.inputs.iter().any(|(input, amount)| {
|
||||||
*amount > 0
|
*amount > 0
|
||||||
@ -375,7 +434,7 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.unwrap_or(false)
|
.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
|
RecipeIngredientQuantity::All
|
||||||
} else if at_least_some_ingredients {
|
} else if at_least_some_ingredients {
|
||||||
RecipeIngredientQuantity::Some
|
RecipeIngredientQuantity::Some
|
||||||
@ -386,129 +445,19 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
ordered_recipes.sort_by_key(|(_, recipe, state)| (*state, recipe.output.0.name()));
|
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
|
// 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
|
for (i, (name, recipe, quantity)) in ordered_recipes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(_name, recipe, _quantity)| match &self.show.crafting_tab {
|
.filter(|(_, recipe, _)| self.show.crafting_tab.satisfies(recipe.output.0.as_ref()))
|
||||||
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,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let button = Button::image(
|
let button = Button::image(
|
||||||
@ -562,11 +511,11 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Ingredients
|
// Selected Recipe
|
||||||
if let Some(recipe) = state
|
if let Some((recipe_name, recipe)) = state
|
||||||
.selected_recipe
|
.selected_recipe
|
||||||
.as_ref()
|
.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
|
// Title
|
||||||
Text::new(&recipe.output.0.name())
|
Text::new(&recipe.output.0.name())
|
||||||
@ -576,6 +525,132 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.parent(state.ids.window)
|
.parent(state.ids.window)
|
||||||
.set(state.ids.title_ing, ui);
|
.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
|
// Ingredient images with tooltip
|
||||||
if state.ids.ingredient_frame.len() < recipe.inputs().len() {
|
if state.ids.ingredient_frame.len() < recipe.inputs().len() {
|
||||||
state.update(|state| {
|
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
|
// Scrollbars
|
||||||
Scrollbar::y_axis(state.ids.align_rec)
|
Scrollbar::y_axis(state.ids.align_rec)
|
||||||
.thickness(5.0)
|
.thickness(5.0)
|
||||||
@ -735,15 +860,6 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.rgba(0.33, 0.33, 0.33, 1.0)
|
.rgba(0.33, 0.33, 0.33, 1.0)
|
||||||
.set(state.ids.scrollbar_ing, ui);
|
.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
|
events
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,15 +88,6 @@ image_ids! {
|
|||||||
// Social Window
|
// Social Window
|
||||||
social_frame_on: "voxygen.element.misc_bg.social_frame",
|
social_frame_on: "voxygen.element.misc_bg.social_frame",
|
||||||
social_bg_on: "voxygen.element.misc_bg.social_bg",
|
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
|
||||||
crafting_window: "voxygen.element.misc_bg.crafting",
|
crafting_window: "voxygen.element.misc_bg.crafting",
|
||||||
@ -110,6 +101,7 @@ image_ids! {
|
|||||||
icon_dismantle: "voxygen.element.icons.dismantle",
|
icon_dismantle: "voxygen.element.icons.dismantle",
|
||||||
icon_food: "voxygen.element.icons.foods",
|
icon_food: "voxygen.element.icons.foods",
|
||||||
icon_glider: "voxygen.element.icons.gliders",
|
icon_glider: "voxygen.element.icons.gliders",
|
||||||
|
icon_globe: "voxygen.element.icons.globe",
|
||||||
icon_potion: "voxygen.element.icons.potions",
|
icon_potion: "voxygen.element.icons.potions",
|
||||||
icon_utility: "voxygen.element.icons.utilities",
|
icon_utility: "voxygen.element.icons.utilities",
|
||||||
icon_weapon: "voxygen.element.icons.weapons",
|
icon_weapon: "voxygen.element.icons.weapons",
|
||||||
@ -403,6 +395,10 @@ image_ids! {
|
|||||||
close_button_hover: "voxygen.element.buttons.close_btn_hover",
|
close_button_hover: "voxygen.element.buttons.close_btn_hover",
|
||||||
close_button_press: "voxygen.element.buttons.close_btn_press",
|
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
|
// Inventory
|
||||||
collapse_btn: "voxygen.element.buttons.inv_collapse",
|
collapse_btn: "voxygen.element.buttons.inv_collapse",
|
||||||
collapse_btn_hover: "voxygen.element.buttons.inv_collapse_hover",
|
collapse_btn_hover: "voxygen.element.buttons.inv_collapse_hover",
|
||||||
|
@ -31,7 +31,7 @@ use buffs::BuffsBar;
|
|||||||
use buttons::Buttons;
|
use buttons::Buttons;
|
||||||
use chat::Chat;
|
use chat::Chat;
|
||||||
use chrono::NaiveTime;
|
use chrono::NaiveTime;
|
||||||
use crafting::{Crafting, SelectedCraftingTab};
|
use crafting::{Crafting, CraftingTab};
|
||||||
use diary::{Diary, SelectedSkillTree};
|
use diary::{Diary, SelectedSkillTree};
|
||||||
use esc_menu::EscMenu;
|
use esc_menu::EscMenu;
|
||||||
use group::Group;
|
use group::Group;
|
||||||
@ -44,7 +44,7 @@ use prompt_dialog::PromptDialog;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings_window::{SettingsTab, SettingsWindow};
|
use settings_window::{SettingsTab, SettingsWindow};
|
||||||
use skillbar::Skillbar;
|
use skillbar::Skillbar;
|
||||||
use social::{Social, SocialTab};
|
use social::Social;
|
||||||
use trade::Trade;
|
use trade::Trade;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -546,8 +546,9 @@ pub struct Show {
|
|||||||
ingame: bool,
|
ingame: bool,
|
||||||
settings_tab: SettingsTab,
|
settings_tab: SettingsTab,
|
||||||
skilltreetab: SelectedSkillTree,
|
skilltreetab: SelectedSkillTree,
|
||||||
crafting_tab: SelectedCraftingTab,
|
crafting_tab: CraftingTab,
|
||||||
social_tab: SocialTab,
|
crafting_search_key: Option<String>,
|
||||||
|
social_search_key: Option<String>,
|
||||||
want_grab: bool,
|
want_grab: bool,
|
||||||
stats: bool,
|
stats: bool,
|
||||||
free_look: bool,
|
free_look: bool,
|
||||||
@ -561,6 +562,10 @@ impl Show {
|
|||||||
self.bag = open;
|
self.bag = open;
|
||||||
self.map = false;
|
self.map = false;
|
||||||
self.want_grab = !open;
|
self.want_grab = !open;
|
||||||
|
|
||||||
|
if !open {
|
||||||
|
self.crafting = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,6 +595,10 @@ impl Show {
|
|||||||
|
|
||||||
fn social(&mut self, open: bool) {
|
fn social(&mut self, open: bool) {
|
||||||
if !self.esc_menu {
|
if !self.esc_menu {
|
||||||
|
if !self.social && open {
|
||||||
|
// rising edge detector
|
||||||
|
self.search_social_players(None);
|
||||||
|
}
|
||||||
self.social = open;
|
self.social = open;
|
||||||
self.diary = false;
|
self.diary = false;
|
||||||
self.want_grab = !open;
|
self.want_grab = !open;
|
||||||
@ -598,6 +607,10 @@ impl Show {
|
|||||||
|
|
||||||
fn crafting(&mut self, open: bool) {
|
fn crafting(&mut self, open: bool) {
|
||||||
if !self.esc_menu {
|
if !self.esc_menu {
|
||||||
|
if !self.crafting && open {
|
||||||
|
// rising edge detector
|
||||||
|
self.search_crafting_recipe(None);
|
||||||
|
}
|
||||||
self.crafting = open;
|
self.crafting = open;
|
||||||
self.bag = open;
|
self.bag = open;
|
||||||
self.map = false;
|
self.map = false;
|
||||||
@ -711,11 +724,6 @@ impl Show {
|
|||||||
|
|
||||||
fn toggle_crafting(&mut self) { self.crafting(!self.crafting) }
|
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) {
|
fn toggle_spell(&mut self) {
|
||||||
self.diary = !self.diary;
|
self.diary = !self.diary;
|
||||||
self.bag = false;
|
self.bag = false;
|
||||||
@ -730,8 +738,14 @@ impl Show {
|
|||||||
self.social = false;
|
self.social = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_crafting_tab(&mut self, sel_cat: SelectedCraftingTab) {
|
fn selected_crafting_tab(&mut self, sel_cat: CraftingTab) { self.crafting_tab = sel_cat; }
|
||||||
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
|
/// If all of the menus are closed, adjusts coordinates of cursor to center
|
||||||
@ -890,8 +904,9 @@ impl Hud {
|
|||||||
group_menu: false,
|
group_menu: false,
|
||||||
settings_tab: SettingsTab::Interface,
|
settings_tab: SettingsTab::Interface,
|
||||||
skilltreetab: SelectedSkillTree::General,
|
skilltreetab: SelectedSkillTree::General,
|
||||||
crafting_tab: SelectedCraftingTab::Armor,
|
crafting_tab: CraftingTab::All,
|
||||||
social_tab: SocialTab::Online,
|
crafting_search_key: None,
|
||||||
|
social_search_key: None,
|
||||||
want_grab: true,
|
want_grab: true,
|
||||||
ingame: true,
|
ingame: true,
|
||||||
stats: false,
|
stats: false,
|
||||||
@ -2368,7 +2383,6 @@ impl Hud {
|
|||||||
Some(bag::Event::Close) => {
|
Some(bag::Event::Close) => {
|
||||||
self.show.stats = false;
|
self.show.stats = false;
|
||||||
self.show.bag(false);
|
self.show.bag(false);
|
||||||
self.show.crafting(false);
|
|
||||||
if !self.show.social {
|
if !self.show.social {
|
||||||
self.show.want_grab = true;
|
self.show.want_grab = true;
|
||||||
self.force_ungrab = false;
|
self.force_ungrab = false;
|
||||||
@ -2469,7 +2483,6 @@ impl Hud {
|
|||||||
crafting::Event::Close => {
|
crafting::Event::Close => {
|
||||||
self.show.stats = false;
|
self.show.stats = false;
|
||||||
self.show.crafting(false);
|
self.show.crafting(false);
|
||||||
self.show.bag(false);
|
|
||||||
if !self.show.social {
|
if !self.show.social {
|
||||||
self.show.want_grab = true;
|
self.show.want_grab = true;
|
||||||
self.force_ungrab = false;
|
self.force_ungrab = false;
|
||||||
@ -2480,6 +2493,12 @@ impl Hud {
|
|||||||
crafting::Event::ChangeCraftingTab(sel_cat) => {
|
crafting::Event::ChangeCraftingTab(sel_cat) => {
|
||||||
self.show.selected_crafting_tab(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
|
self.force_ungrab = true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
social::Event::ChangeSocialTab(social_tab) => {
|
social::Event::Focus(widget_id) => {
|
||||||
self.show.open_social_tab(social_tab)
|
self.to_focus = Some(Some(widget_id));
|
||||||
},
|
},
|
||||||
social::Event::Invite(uid) => events.push(Event::InviteMember(uid)),
|
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 common::{comp::group, uid::Uid};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
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,
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -27,25 +27,14 @@ widget_ids! {
|
|||||||
icon,
|
icon,
|
||||||
scrollbar,
|
scrollbar,
|
||||||
online_align,
|
online_align,
|
||||||
online_tab,
|
|
||||||
names_align,
|
|
||||||
name_txt,
|
|
||||||
player_levels[],
|
|
||||||
player_names[],
|
player_names[],
|
||||||
player_zones[],
|
|
||||||
online_txt,
|
online_txt,
|
||||||
online_no,
|
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,
|
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)>,
|
selected_uid: Option<(Uid, Instant)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SocialTab {
|
|
||||||
Online,
|
|
||||||
Friends,
|
|
||||||
Faction,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
pub struct Social<'a> {
|
pub struct Social<'a> {
|
||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
@ -106,7 +89,8 @@ impl<'a> Social<'a> {
|
|||||||
pub enum Event {
|
pub enum Event {
|
||||||
Close,
|
Close,
|
||||||
Invite(Uid),
|
Invite(Uid),
|
||||||
ChangeSocialTab(SocialTab),
|
Focus(widget::Id),
|
||||||
|
SearchPlayers(Option<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Widget for Social<'a> {
|
impl<'a> Widget for Social<'a> {
|
||||||
@ -145,33 +129,27 @@ impl<'a> Widget for Social<'a> {
|
|||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.desc_text_color(TEXT_COLOR);
|
.desc_text_color(TEXT_COLOR);
|
||||||
|
|
||||||
// Window frame and BG
|
// Window BG
|
||||||
let pos = if self.show.group || self.show.group_menu {
|
Image::new(self.imgs.social_bg_on)
|
||||||
200.0
|
.bottom_left_with_margins_on(ui.window, 308.0, 25.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)
|
|
||||||
.color(Some(UI_MAIN))
|
.color(Some(UI_MAIN))
|
||||||
.w_h(280.0, 460.0)
|
.w_h(280.0, 460.0)
|
||||||
.set(state.ids.bg, ui);
|
.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)
|
.middle_of(state.ids.bg)
|
||||||
.color(Some(UI_HIGHLIGHT_0))
|
.color(Some(UI_HIGHLIGHT_0))
|
||||||
.w_h(280.0, 460.0)
|
.w_h(280.0, 460.0)
|
||||||
.set(state.ids.frame, ui);
|
.set(state.ids.frame, ui);
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
Image::new(self.imgs.social)
|
Image::new(self.imgs.social)
|
||||||
.w_h(30.0, 30.0)
|
.w_h(30.0, 30.0)
|
||||||
@ -200,381 +178,269 @@ impl<'a> Widget for Social<'a> {
|
|||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.title, ui);
|
.set(state.ids.title, ui);
|
||||||
|
|
||||||
// Tabs Buttons
|
let players = self
|
||||||
// Online Tab Button
|
.client
|
||||||
if Button::image(match &self.show.social_tab {
|
.player_list()
|
||||||
SocialTab::Online => self.imgs.social_tab_online,
|
.iter()
|
||||||
_ => self.imgs.social_tab_inact,
|
.filter(|(_, p)| p.is_online);
|
||||||
})
|
let player_count = players.clone().count();
|
||||||
.w_h(30.0, 44.0)
|
|
||||||
.image_color(match &self.show.social_tab {
|
// Content Alignment
|
||||||
SocialTab::Online => UI_MAIN,
|
Rectangle::fill_with([270.0, 346.0], color::TRANSPARENT)
|
||||||
_ => Color::Rgba(1.0, 1.0, 1.0, 0.6),
|
.mid_top_with_margin_on(state.ids.frame, 74.0)
|
||||||
})
|
.scroll_kids_vertically()
|
||||||
.top_right_with_margins_on(state.ids.frame, 50.0, -27.0)
|
.set(state.ids.online_align, ui);
|
||||||
.set(state.ids.online_tab, ui)
|
Scrollbar::y_axis(state.ids.online_align)
|
||||||
.was_clicked()
|
.thickness(4.0)
|
||||||
{
|
.color(Color::Rgba(0.79, 1.09, 1.09, 0.0))
|
||||||
events.push(Event::ChangeSocialTab(SocialTab::Online));
|
.set(state.ids.scrollbar, ui);
|
||||||
}
|
|
||||||
// Friends Tab Button
|
// Online Text
|
||||||
if Button::image(match &self.show.social_tab {
|
Text::new(&self.localized_strings.get("hud.social.online"))
|
||||||
SocialTab::Friends => self.imgs.social_tab_act,
|
.bottom_left_with_margins_on(state.ids.frame, 18.0, 10.0)
|
||||||
_ => self.imgs.social_tab_inact,
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
})
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
.w_h(30.0, 44.0)
|
.color(TEXT_COLOR)
|
||||||
.hover_image(match &self.show.social_tab {
|
.set(state.ids.online_txt, ui);
|
||||||
SocialTab::Friends => self.imgs.social_tab_act,
|
Text::new(&player_count.to_string())
|
||||||
_ => self.imgs.social_tab_inact_hover,
|
.right_from(state.ids.online_txt, 5.0)
|
||||||
})
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.press_image(match &self.show.social_tab {
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
SocialTab::Friends => self.imgs.social_tab_act,
|
.color(TEXT_COLOR)
|
||||||
_ => self.imgs.social_tab_inact_press,
|
.set(state.ids.online_no, ui);
|
||||||
})
|
// Adjust widget_id struct vec length to player count
|
||||||
.down_from(state.ids.online_tab, 0.0)
|
if state.ids.player_names.len() < player_count {
|
||||||
.image_color(match &self.show.social_tab {
|
state.update(|s| {
|
||||||
SocialTab::Friends => UI_MAIN,
|
s.ids
|
||||||
_ => Color::Rgba(1.0, 1.0, 1.0, 0.6),
|
.player_names
|
||||||
})
|
.resize(player_count, &mut ui.widget_id_generator())
|
||||||
.set(state.ids.friends_tab, ui)
|
})
|
||||||
.was_clicked()
|
};
|
||||||
{
|
|
||||||
events.push(Event::ChangeSocialTab(SocialTab::Friends));
|
// Filter out yourself from the online list and perform search
|
||||||
}
|
let my_uid = self.client.uid();
|
||||||
// Faction Tab Button
|
let mut player_list = players
|
||||||
if Button::image(match &self.show.social_tab {
|
.filter(|(uid, _)| Some(**uid) != my_uid)
|
||||||
SocialTab::Friends => self.imgs.social_tab_act,
|
.filter(|(_, player)| {
|
||||||
_ => self.imgs.social_tab_inact,
|
self.show
|
||||||
})
|
.social_search_key
|
||||||
.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
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|character| character.name.to_lowercase())
|
.map(|search_key| {
|
||||||
.unwrap_or_else(|| player.player_alias.to_string())
|
search_key
|
||||||
});
|
.to_lowercase()
|
||||||
for (i, (&uid, player_info)) in player_list.into_iter().enumerate() {
|
.split_whitespace()
|
||||||
let hide_username = true;
|
.all(|substring| {
|
||||||
let zone = ""; // TODO Add real zone
|
let player_alias = &player.player_alias.to_lowercase();
|
||||||
let selected = state.selected_uid.map_or(false, |u| u.0 == uid);
|
let character_name = player
|
||||||
let alias = &player_info.player_alias;
|
.character
|
||||||
let zone_name = match &player_info.character {
|
.as_ref()
|
||||||
None => self.localized_strings.get("hud.group.in_menu").to_string(), /* character select or spectating */
|
.map(|character| character.name.to_lowercase());
|
||||||
_ => format!("{} ", &zone),
|
player_alias.contains(substring)
|
||||||
};
|
|| character_name
|
||||||
let name_text = match &player_info.character {
|
.map(|cn| cn.contains(substring))
|
||||||
Some(character) => {
|
.unwrap_or(false)
|
||||||
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
|
|
||||||
})
|
})
|
||||||
.press_image(if selected {
|
.unwrap_or(true)
|
||||||
self.imgs.selection
|
})
|
||||||
|
.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 {
|
} else {
|
||||||
self.imgs.selection_press
|
format!("[{}] {}", alias, &character.name)
|
||||||
})
|
}
|
||||||
.label(&name_text)
|
},
|
||||||
.label_font_size(self.fonts.cyri.scale(14))
|
None => format!(
|
||||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
"{} [{}]",
|
||||||
.label_font_id(self.fonts.cyri.conrod_id)
|
alias.clone(),
|
||||||
.label_color(TEXT_COLOR)
|
self.localized_strings.get("hud.group.in_menu").to_string()
|
||||||
.with_tooltip(
|
), // character select or spectating
|
||||||
self.tooltip_manager,
|
};
|
||||||
&acc_name_txt,
|
let acc_name_txt = format!(
|
||||||
"",
|
"{}: {}",
|
||||||
&button_tooltip,
|
&self.localized_strings.get("hud.social.account"),
|
||||||
TEXT_COLOR,
|
alias
|
||||||
)
|
);
|
||||||
.set(state.ids.player_names[i], ui);
|
// Player name widget
|
||||||
// Player Zones
|
let button = Button::image(if !selected {
|
||||||
Button::image(if !selected {
|
self.imgs.nothing
|
||||||
self.imgs.nothing
|
} else {
|
||||||
} else {
|
self.imgs.selection
|
||||||
self.imgs.selection
|
})
|
||||||
})
|
.hover_image(if selected {
|
||||||
.w_h(94.0, 20.0)
|
self.imgs.selection
|
||||||
.right_from(state.ids.player_levels[i], 2.0)
|
} else {
|
||||||
.label(&zone_name)
|
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_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_font_id(self.fonts.cyri.conrod_id)
|
||||||
.label_color(TEXT_COLOR)
|
.label_color(TEXT_COLOR)
|
||||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
.with_tooltip(
|
||||||
.parent(state.ids.zones_align)
|
self.tooltip_manager,
|
||||||
.set(state.ids.player_zones[i], ui);
|
&acc_name_txt,
|
||||||
// Check for click
|
"",
|
||||||
if ui
|
&button_tooltip,
|
||||||
.widget_input(state.ids.player_names[i])
|
TEXT_COLOR,
|
||||||
.clicks()
|
)
|
||||||
.left()
|
.set(state.ids.player_names[i], ui)
|
||||||
.next()
|
.was_clicked()
|
||||||
.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()
|
|
||||||
{
|
{
|
||||||
if let Some(uid) = selected_to_invite {
|
state.update(|s| s.selected_uid = Some((uid, Instant::now())));
|
||||||
events.push(Event::Invite(uid));
|
|
||||||
state.update(|s| {
|
|
||||||
s.selected_uid = None;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // 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
|
events
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user