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
|
- 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