diff --git a/assets/voxygen/element/buttons/settings_button_pressed.vox b/assets/voxygen/element/buttons/settings_button_pressed.vox index 451dd19486..69ea91e107 100644 --- a/assets/voxygen/element/buttons/settings_button_pressed.vox +++ b/assets/voxygen/element/buttons/settings_button_pressed.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5aebe92b4f9b3e27a0c42899d5d8a6e6ea8f69251c901104003b11eded10bb5 -size 7644 +oid sha256:a4b72716beed6e09099509b44cb9799fe336d9b20a526b8d14c2dff92e99657f +size 50359 diff --git a/assets/voxygen/element/buttons/social_tab.vox b/assets/voxygen/element/buttons/social_tab.vox new file mode 100644 index 0000000000..9cf9ce4319 --- /dev/null +++ b/assets/voxygen/element/buttons/social_tab.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e7b8fa60b1f44ba2f4c3bd2af4ac96ca0c77224f0539cb82ff55c01b558fb48 +size 5528 diff --git a/assets/voxygen/element/buttons/social_tab_hover.vox b/assets/voxygen/element/buttons/social_tab_hover.vox new file mode 100644 index 0000000000..e69ea03317 --- /dev/null +++ b/assets/voxygen/element/buttons/social_tab_hover.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b4aa1df2ce98140c9fa79a518df1f9c66e6528a8a7e7346a6371ba9a87199c3 +size 5528 diff --git a/assets/voxygen/element/buttons/social_tab_press.vox b/assets/voxygen/element/buttons/social_tab_press.vox new file mode 100644 index 0000000000..7c164ce849 --- /dev/null +++ b/assets/voxygen/element/buttons/social_tab_press.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b2cc35617c963a4b76483c9fdda82a94c545bf2c9c2fd23a8a6efa53830338b +size 3576 diff --git a/assets/voxygen/element/buttons/social_tab_pressed.vox b/assets/voxygen/element/buttons/social_tab_pressed.vox new file mode 100644 index 0000000000..3f35488cbb --- /dev/null +++ b/assets/voxygen/element/buttons/social_tab_pressed.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ecc52840a6a478fb58e4d6cd171932386bf426ea67e2fd6d8f70c7fc2496e87 +size 7056 diff --git a/assets/voxygen/element/frames/social_frame.vox b/assets/voxygen/element/frames/social_frame.vox new file mode 100644 index 0000000000..0f4e305b0e --- /dev/null +++ b/assets/voxygen/element/frames/social_frame.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:277cec8316a95763e12c82e1a301b3340a11e46e059d81fddcaf4ba28da14ae6 +size 89525 diff --git a/assets/voxygen/element/frames/window_3.vox b/assets/voxygen/element/frames/window_3.vox index c9ef3917af..af01983c4d 100644 --- a/assets/voxygen/element/frames/window_3.vox +++ b/assets/voxygen/element/frames/window_3.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee3d7c5a94372b9ec1f5544151112deadcbfc0bc2571c8cf2efba350e448b126 -size 239600 +oid sha256:664d22942cb76f938ea4b7b68efc18dc9e2305c3e667ab7ea5ad256b2b42cea0 +size 241316 diff --git a/assets/world/structure/dungeon/ruins_2.vox b/assets/world/structure/dungeon/ruins_2.vox index 4c07795b0a..c8eb22eed8 100644 --- a/assets/world/structure/dungeon/ruins_2.vox +++ b/assets/world/structure/dungeon/ruins_2.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e56e795072bc62d43dfd4e94e5453f06b5715359133c31e051d2bc50f1bf439a -size 707824 +oid sha256:439b57e8560b6b9167a992e83d94bc37da98e74552d304ed864cf1a3456f2c28 +size 750932 diff --git a/assets/world/structure/natural/witch-hut.vox b/assets/world/structure/natural/witch-hut.vox index 91e81d3762..509ca4884f 100644 --- a/assets/world/structure/natural/witch-hut.vox +++ b/assets/world/structure/natural/witch-hut.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9fa7c5fc64422738036be8462fb511487ece5f9233f0f8a6fe89d9f023335f0 -size 59560 +oid sha256:13880c69c5b854f69797825124d398d27b014ad6e019b64652d0b5f31fe4a964 +size 77844 diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index 15aa1dc7bd..eb3f29296c 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -3,7 +3,7 @@ use conrod_core::{ widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; -use super::{img_ids::Imgs, small_window::SmallWindowType, Fonts, Windows, TEXT_COLOR}; +use super::{img_ids::Imgs, Fonts, Windows, TEXT_COLOR}; use crate::ui::ToggleButton; widget_ids! { @@ -63,7 +63,9 @@ pub enum Event { ToggleBag, ToggleSettings, ToggleMap, - ToggleSmall(SmallWindowType), + ToggleSocial, + ToggleSpell, + ToggleQuest, ToggleCharacter, } @@ -154,6 +156,13 @@ impl<'a> Widget for Buttons<'a> { return Some(Event::ToggleMap); }; + // Other Windows can only be accessed when `Settings` is closed. + // Opening `Settings` will close all other Windows, including the `Bag`. + // Opening the `Map` won't close the previously displayed windows. + Image::new(self.imgs.social) + .w_h(25.0, 25.0) + .left_from(state.ids.settings_button, 10.0) + .set(state.ids.social_button_bg, ui); Image::new(self.imgs.spellbook_button) .w_h(28.0, 25.0) .left_from(state.ids.map_button, 10.0) @@ -172,7 +181,7 @@ impl<'a> Widget for Buttons<'a> { // Opening the `Map` won't close the previously displayed windows. if !(*self.open_windows == Windows::Settings) && self.show_map == false { // 1 Social - if Button::image(self.imgs.social_button) + if Button::image(self.imgs.social) .w_h(25.0, 25.0) .left_from(state.ids.settings_button, 10.0) .hover_image(self.imgs.social_hover) @@ -185,7 +194,7 @@ impl<'a> Widget for Buttons<'a> { .set(state.ids.social_button, ui) .was_clicked() { - return Some(Event::ToggleSmall(SmallWindowType::Social)); + return Some(Event::ToggleSocial); } // 3 Spellbook @@ -202,7 +211,7 @@ impl<'a> Widget for Buttons<'a> { .set(state.ids.spellbook_button, ui) .was_clicked() { - return Some(Event::ToggleSmall(SmallWindowType::Spellbook)); + return Some(Event::ToggleSpell); } // 4 Char-Window @@ -236,7 +245,7 @@ impl<'a> Widget for Buttons<'a> { .set(state.ids.qlog_button, ui) .was_clicked() { - return Some(Event::ToggleSmall(SmallWindowType::QuestLog)); + return Some(Event::ToggleQuest); } } diff --git a/voxygen/src/hud/character_window.rs b/voxygen/src/hud/character_window.rs index 63e0fa2390..25c92c8410 100644 --- a/voxygen/src/hud/character_window.rs +++ b/voxygen/src/hud/character_window.rs @@ -1,4 +1,4 @@ -use super::{img_ids::Imgs, Fonts, TEXT_COLOR, XP_COLOR}; +use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR, XP_COLOR}; use common::comp::Stats; use conrod_core::{ color, @@ -68,6 +68,7 @@ widget_ids! { #[derive(WidgetCommon)] pub struct CharacterWindow<'a> { + _show: &'a Show, imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats, @@ -77,8 +78,9 @@ pub struct CharacterWindow<'a> { } impl<'a> CharacterWindow<'a> { - pub fn new(imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats) -> Self { + pub fn new(_show: &'a Show, stats: &'a Stats, imgs: &'a Imgs, fonts: &'a Fonts) -> Self { Self { + _show, imgs, fonts, stats, @@ -87,6 +89,10 @@ impl<'a> CharacterWindow<'a> { } } +/*pub struct State { + ids: Ids, +}*/ + pub enum Event { Close, } @@ -114,7 +120,7 @@ impl<'a> Widget for CharacterWindow<'a> { // Frame Image::new(self.imgs.window_3) .middle_of(id) - .top_left_with_margins_on(ui.window, 212.0, 215.0) + .top_left_with_margins_on(ui.window, 200.0, 215.0) .w_h(103.0 * 4.0, 122.0 * 4.0) .set(state.charwindow_frame, ui); diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 6025c28266..fb5858be9f 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -26,6 +26,14 @@ image_ids! { // Missing: Buff Frame Animation .gif ?! we could do animation in ui.maintain, or in shader? window_frame: "voxygen.element.frames.window2", + // Social Window + social_button: "voxygen.element.buttons.social_tab", + social_button_pressed: "voxygen.element.buttons.social_tab_pressed", + social_button_hover: "voxygen.element.buttons.social_tab_hover", + social_button_press: "voxygen.element.buttons.social_tab_press", + social_frame: "voxygen.element.frames.social_frame", + + // Settings Window settings_frame_r: "voxygen.element.frames.settings_r", settings_frame_l: "voxygen.element.frames.settings_l", @@ -85,7 +93,7 @@ image_ids! { settings_hover: "voxygen.element.buttons.settings_hover", settings_press: "voxygen.element.buttons.settings_press", - social_button: "voxygen.element.buttons.social", + social: "voxygen.element.buttons.social", social_hover: "voxygen.element.buttons.social_hover", social_press: "voxygen.element.buttons.social_press", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 95ca203571..970f33d4e1 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -6,9 +6,11 @@ mod esc_menu; mod img_ids; mod map; mod minimap; +mod quest; mod settings_window; mod skillbar; -mod small_window; +mod social; +mod spell; pub use settings_window::ScaleChange; @@ -20,10 +22,12 @@ use esc_menu::EscMenu; use img_ids::Imgs; use map::Map; use minimap::MiniMap; +use quest::Quest; use serde::{Deserialize, Serialize}; use settings_window::{SettingsTab, SettingsWindow}; use skillbar::Skillbar; -use small_window::{SmallWindow, SmallWindowType}; +use social::{Social, SocialTab}; +use spell::Spell; use crate::{ render::{Consts, Globals, Renderer}, @@ -50,6 +54,7 @@ use crate::{discord, discord::DiscordUpdate}; const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); const TEXT_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0); +const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); const MANA_COLOR: Color = Color::Rgba(0.42, 0.41, 0.66, 1.0); const META_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0); @@ -109,10 +114,14 @@ widget_ids! { character_window, minimap, bag, + social, + quest, + spell, skillbar, buttons, esc_menu, small_window, + social_window, settings_window, } } @@ -155,9 +164,7 @@ pub enum Event { // `map` is not here because it currently is displayed over the top of other open windows. #[derive(PartialEq)] pub enum Windows { - Settings, // Display settings window. - CharacterAnd(Option), // Show character window + optionally another. - Small(SmallWindowType), + Settings, // Display settings window. None, } @@ -173,6 +180,10 @@ pub struct Show { help: bool, debug: bool, bag: bool, + social: bool, + spell: bool, + quest: bool, + character_window: bool, esc_menu: bool, open_windows: Windows, map: bool, @@ -180,6 +191,8 @@ pub struct Show { mini_map: bool, ingame: bool, settings_tab: SettingsTab, + social_tab: SocialTab, + want_grab: bool, } impl Show { @@ -195,6 +208,29 @@ impl Show { self.bag = false; self.want_grab = !open; } + fn character_window(&mut self, open: bool) { + self.character_window = open; + self.bag = false; + self.want_grab = !open; + } + fn social(&mut self, open: bool) { + self.social = open; + self.spell = false; + self.quest = false; + self.want_grab = !open; + } + fn spell(&mut self, open: bool) { + self.social = false; + self.spell = open; + self.quest = false; + self.want_grab = !open; + } + fn quest(&mut self, open: bool) { + self.social = false; + self.spell = false; + self.quest = open; + self.want_grab = !open; + } fn toggle_map(&mut self) { self.map(!self.map) } @@ -203,28 +239,8 @@ impl Show { self.mini_map = !self.mini_map; } - fn toggle_small(&mut self, target: SmallWindowType) { - self.open_windows = match self.open_windows { - Windows::Small(small) if small == target => Windows::None, - Windows::None | Windows::Small(_) => Windows::Small(target), - Windows::CharacterAnd(small) => match small { - Some(small) if small == target => Windows::CharacterAnd(None), - _ => Windows::CharacterAnd(Some(target)), - }, - Windows::Settings => Windows::Settings, - }; - } - fn toggle_char_window(&mut self) { - self.open_windows = match self.open_windows { - Windows::CharacterAnd(small) => match small { - Some(small) => Windows::Small(small), - None => Windows::None, - }, - Windows::Small(small) => Windows::CharacterAnd(Some(small)), - Windows::None => Windows::CharacterAnd(None), - Windows::Settings => Windows::Settings, - } + self.character_window = !self.character_window } fn settings(&mut self, open: bool) { @@ -234,6 +250,9 @@ impl Show { Windows::None }; self.bag = false; + self.social = false; + self.spell = false; + self.quest = false; self.want_grab = !open; } fn toggle_settings(&mut self) { @@ -255,6 +274,10 @@ impl Show { if self.bag || self.esc_menu || self.map + || self.social + || self.quest + || self.spell + || self.character_window || match self.open_windows { Windows::None => false, _ => true, @@ -263,6 +286,10 @@ impl Show { self.bag = false; self.esc_menu = false; self.map = false; + self.social = false; + self.quest = false; + self.spell = false; + self.character_window = false; self.open_windows = Windows::None; self.want_grab = true; } else { @@ -278,6 +305,30 @@ impl Show { self.bag = false; self.want_grab = false; } + + fn toggle_social(&mut self) { + self.social = !self.social; + self.spell = false; + self.quest = false; + } + + fn open_social_tab(&mut self, social_tab: SocialTab) { + self.social_tab = social_tab; + self.spell = false; + self.quest = false; + } + + fn toggle_spell(&mut self) { + self.spell = !self.spell; + self.social = false; + self.quest = false; + } + + fn toggle_quest(&mut self) { + self.quest = !self.quest; + self.spell = false; + self.social = false; + } } pub struct Hud { @@ -323,9 +374,14 @@ impl Hud { open_windows: Windows::None, map: false, ui: true, + social: false, + quest: false, + spell: false, + character_window: false, inventory_test_button: false, mini_map: false, settings_tab: SettingsTab::Interface, + social_tab: SocialTab::Online, want_grab: true, ingame: true, }, @@ -347,27 +403,7 @@ impl Hud { let version = format!("{}-{}", env!("CARGO_PKG_VERSION"), common::util::GIT_HASH); - // Nametags and healthbars if self.show.ingame { - let ecs = client.state().ecs(); - let pos = ecs.read_storage::(); - let stats = ecs.read_storage::(); - let players = ecs.read_storage::(); - let scales = ecs.read_storage::(); - let entities = ecs.entities(); - let me = client.entity(); - let view_distance = client.view_distance().unwrap_or(1); - // Get player position. - let player_pos = client - .state() - .ecs() - .read_storage::() - .get(client.entity()) - .map_or(Vec3::zero(), |pos| pos.0); - let mut name_id_walker = self.ids.name_tags.walk(); - let mut health_id_walker = self.ids.health_bars.walk(); - let mut health_back_id_walker = self.ids.health_bar_backs.walk(); - // Crosshair Image::new( // TODO: Do we want to match on this every frame? @@ -392,6 +428,26 @@ impl Hud { .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6))) .set(self.ids.crosshair_inner, ui_widgets); + // Nametags and healthbars + let ecs = client.state().ecs(); + let pos = ecs.read_storage::(); + let stats = ecs.read_storage::(); + let players = ecs.read_storage::(); + let scales = ecs.read_storage::(); + let entities = ecs.entities(); + let me = client.entity(); + let view_distance = client.view_distance().unwrap_or(1); + // Get player position. + let player_pos = client + .state() + .ecs() + .read_storage::() + .get(client.entity()) + .map_or(Vec3::zero(), |pos| pos.0); + let mut name_id_walker = self.ids.name_tags.walk(); + let mut health_id_walker = self.ids.health_bars.walk(); + let mut health_back_id_walker = self.ids.health_bar_backs.walk(); + // Render Name Tags for (pos, name, scale) in (&entities, &pos, &stats, players.maybe(), scales.maybe()) .join() @@ -592,7 +648,9 @@ impl Hud { Some(buttons::Event::ToggleBag) => self.show.toggle_bag(), Some(buttons::Event::ToggleSettings) => self.show.toggle_settings(), Some(buttons::Event::ToggleCharacter) => self.show.toggle_char_window(), - Some(buttons::Event::ToggleSmall(small)) => self.show.toggle_small(small), + Some(buttons::Event::ToggleSocial) => self.show.toggle_social(), + Some(buttons::Event::ToggleSpell) => self.show.toggle_spell(), + Some(buttons::Event::ToggleQuest) => self.show.toggle_quest(), Some(buttons::Event::ToggleMap) => self.show.toggle_map(), None => {} } @@ -702,40 +760,66 @@ impl Hud { } } - // Small Window - if let Windows::Small(small) | Windows::CharacterAnd(Some(small)) = self.show.open_windows { - match SmallWindow::new(small, &self.show, &self.imgs, &self.fonts) - .set(self.ids.small_window, ui_widgets) + // Social Window + if self.show.social { + for event in Social::new( + /*&global_state,*/ &self.show, + client, + &self.imgs, + &self.fonts, + ) + .set(self.ids.social_window, ui_widgets) { - Some(small_window::Event::Close) => { - self.show.open_windows = match self.show.open_windows { - Windows::Small(_) => Windows::None, - Windows::CharacterAnd(_) => Windows::CharacterAnd(None), - _ => Windows::Settings, + match event { + social::Event::Close => self.show.social(false), + social::Event::ChangeSocialTab(social_tab) => { + self.show.open_social_tab(social_tab) } } - None => {} } } // Character Window - if let Windows::CharacterAnd(small) = self.show.open_windows { + if self.show.character_window { let ecs = client.state().ecs(); let stats = ecs.read_storage::(); let player_stats = stats.get(client.entity()).unwrap(); - match CharacterWindow::new(&self.imgs, &self.fonts, &player_stats) + match CharacterWindow::new(&self.show, &player_stats, &self.imgs, &self.fonts) .set(self.ids.character_window, ui_widgets) { Some(character_window::Event::Close) => { - self.show.open_windows = match small { - Some(small) => Windows::Small(small), - None => Windows::None, - } + self.show.character_window(false); + self.force_ungrab = true; } None => {} } } + // Spellbook + if self.show.spell { + match Spell::new(&self.show, client, &self.imgs, &self.fonts) + .set(self.ids.spell, ui_widgets) + { + Some(spell::Event::Close) => { + self.show.spell(false); + self.force_ungrab = true; + } + None => {} + } + } + + // Quest Log + if self.show.quest { + match Quest::new(&self.show, client, &self.imgs, &self.fonts) + .set(self.ids.quest, ui_widgets) + { + Some(quest::Event::Close) => { + self.show.quest(false); + self.force_ungrab = true; + } + None => {} + } + } // Map if self.show.map { match Map::new(&self.show, client, &self.imgs, &self.fonts) @@ -866,7 +950,7 @@ impl Hud { true } GameInput::QuestLog => { - self.show.toggle_small(SmallWindowType::QuestLog); + self.show.toggle_quest(); true } GameInput::CharacterWindow => { @@ -874,11 +958,11 @@ impl Hud { true } GameInput::Social => { - self.show.toggle_small(SmallWindowType::Social); + self.show.toggle_social(); true } GameInput::Spellbook => { - self.show.toggle_small(SmallWindowType::Spellbook); + self.show.toggle_spell(); true } GameInput::Settings => { diff --git a/voxygen/src/hud/quest.rs b/voxygen/src/hud/quest.rs new file mode 100644 index 0000000000..e5deb06b0d --- /dev/null +++ b/voxygen/src/hud/quest.rs @@ -0,0 +1,114 @@ +use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR}; +use conrod_core::{ + color, + widget::{self, Button, Image, Rectangle, Text}, + widget_ids, /*, Color*/ + Colorable, Positionable, Sizeable, Widget, WidgetCommon, +}; + +use client::{self, Client}; + +widget_ids! { + pub struct Ids { + quest_frame, + quest_close, + quest_title, + frame, + content_align, + } +} + +#[derive(WidgetCommon)] +pub struct Quest<'a> { + _show: &'a Show, + _client: &'a Client, + + imgs: &'a Imgs, + fonts: &'a Fonts, + #[conrod(common_builder)] + common: widget::CommonBuilder, +} + +impl<'a> Quest<'a> { + pub fn new(show: &'a Show, _client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self { + Self { + _show: show, + imgs, + _client, + fonts: fonts, + common: widget::CommonBuilder::default(), + } + } +} + +/*pub struct State { + ids: Ids, +}*/ + +pub enum Event { + Close, +} + +impl<'a> Widget for Quest<'a> { + type State = Ids; + type Style = (); + type Event = Option; + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + Ids::new(id_gen) + } + + fn style(&self) -> Self::Style { + () + } + + fn update(self, args: widget::UpdateArgs) -> Self::Event { + let widget::UpdateArgs { + id: _, state, ui, .. + } = args; + + if self._show.character_window { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 658.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(state.quest_frame, ui); + } else { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 25.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(state.quest_frame, ui); + } + + // X-Button + if Button::image(self.imgs.close_button) + .w_h(28.0, 28.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(state.quest_frame, 0.0, 0.0) + .set(state.quest_close, ui) + .was_clicked() + { + return Some(Event::Close); + } + + // Title + // TODO: Use an actual character name. + Text::new("Quest") + .mid_top_with_margin_on(state.quest_frame, 6.0) + .font_id(self.fonts.metamorph) + .font_size(14) + .color(TEXT_COLOR) + .set(state.quest_title, ui); + + // Content Alignment + Rectangle::fill_with([95.0 * 4.0, 108.0 * 4.0], color::TRANSPARENT) + .mid_top_with_margin_on(state.quest_frame, 40.0) + .set(state.content_align, ui); + + // Contents + + // Frame + + None + } +} diff --git a/voxygen/src/hud/small_window.rs b/voxygen/src/hud/small_window.rs deleted file mode 100644 index 9dd308ace9..0000000000 --- a/voxygen/src/hud/small_window.rs +++ /dev/null @@ -1,136 +0,0 @@ -use super::{img_ids::Imgs, Fonts, Windows, TEXT_COLOR}; -use crate::hud::Show; -use conrod_core::{ - color, - widget::{self, Button, Image, Rectangle, Text}, - widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon, -}; - -widget_ids! { - struct Ids { - frame, - bg, - title, - icon, - close, - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum SmallWindowType { - Spellbook, - Social, - QuestLog, -} - -#[derive(WidgetCommon)] -pub struct SmallWindow<'a> { - content: SmallWindowType, - show: &'a Show, - - imgs: &'a Imgs, - fonts: &'a Fonts, - - #[conrod(common_builder)] - common: widget::CommonBuilder, -} - -impl<'a> SmallWindow<'a> { - pub fn new(content: SmallWindowType, show: &'a Show, imgs: &'a Imgs, fonts: &'a Fonts) -> Self { - Self { - content, - show, - imgs, - fonts, - common: widget::CommonBuilder::default(), - } - } -} - -pub struct State { - ids: Ids, -} - -pub enum Event { - Close, -} - -impl<'a> Widget for SmallWindow<'a> { - type State = State; - type Style = (); - type Event = Option; - - fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { - State { - ids: Ids::new(id_gen), - } - } - - fn style(&self) -> Self::Style { - () - } - - fn update(self, args: widget::UpdateArgs) -> Self::Event { - let widget::UpdateArgs { state, ui, .. } = args; - - let (title, icon) = match self.content { - SmallWindowType::Social => ("Social", self.imgs.social_icon), - SmallWindowType::Spellbook => ("Spellbook", self.imgs.spellbook_icon), - SmallWindowType::QuestLog => ("QuestLog", self.imgs.questlog_icon), - }; - - // Frame - // TODO: Relative to Char Window? - if let Windows::CharacterAnd(_) = self.show.open_windows { - Image::new(self.imgs.window_frame) - .top_left_with_margins_on(ui.window, 200.0, 658.0) - .w_h(107.0 * 4.0, 125.0 * 4.0) - .set(state.ids.frame, ui); - } else { - Image::new(self.imgs.window_frame) - .top_left_with_margins_on(ui.window, 200.0, 10.0) - .w_h(107.0 * 4.0, 125.0 * 4.0) - .set(state.ids.frame, ui); - } - - // Icon - Image::new(icon) - .w_h(40.0, 40.0) - .top_left_with_margins_on(state.ids.frame, 4.0, 4.0) - .set(state.ids.icon, ui); - - // Content alignment - Rectangle::fill_with([362.0, 418.0], color::TRANSPARENT) - .bottom_right_with_margins_on(state.ids.frame, 17.0, 17.0) - .scroll_kids() - .scroll_kids_vertically() - .set(state.ids.bg, ui); - - // X-Button - if Button::image(self.imgs.close_button) - .w_h(28.0, 28.0) - .hover_image(self.imgs.close_button_hover) - .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(state.ids.frame, 12.0, 0.0) - .set(state.ids.close, ui) - .was_clicked() - { - return Some(Event::Close); - } - // Title - Text::new(title) - .mid_top_with_margin_on(state.ids.frame, 16.0) - .font_id(self.fonts.metamorph) - .font_size(14) - .color(TEXT_COLOR) - .set(state.ids.title, ui); - - match self.content { - SmallWindowType::Social => {} - SmallWindowType::Spellbook => {} - SmallWindowType::QuestLog => {} - } - - None - } -} diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs new file mode 100644 index 0000000000..09160a2500 --- /dev/null +++ b/voxygen/src/hud/social.rs @@ -0,0 +1,281 @@ +use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR, TEXT_COLOR_3}; + +use common::comp; +use conrod_core::{ + color, + widget::{self, Button, Image, Rectangle, Scrollbar, Text}, + widget_ids, /*, Color*/ + Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, +}; +use specs::Join; + +use client::{self, Client}; + +widget_ids! { + pub struct Ids { + social_frame, + social_close, + social_title, + frame, + align, + content_align, + online_tab, + friends_tab, + faction_tab, + online_title, + online_no, + scrollbar, + friends_test, + faction_test, + player_names[], + } +} + +pub enum SocialTab { + Online, + Friends, + Faction, +} + +#[derive(WidgetCommon)] +pub struct Social<'a> { + show: &'a Show, + client: &'a Client, + imgs: &'a Imgs, + fonts: &'a Fonts, + #[conrod(common_builder)] + common: widget::CommonBuilder, +} + +impl<'a> Social<'a> { + pub fn new(show: &'a Show, client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self { + Self { + show: show, + imgs, + client: client, + fonts: fonts, + common: widget::CommonBuilder::default(), + } + } +} + +/*pub struct State { + ids: Ids, +}*/ + +pub enum Event { + Close, + ChangeSocialTab(SocialTab), +} + +impl<'a> Widget for Social<'a> { + type State = Ids; + type Style = (); + type Event = Vec; + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + Ids::new(id_gen) + } + + fn style(&self) -> Self::Style { + () + } + + fn update(self, args: widget::UpdateArgs) -> Self::Event { + let widget::UpdateArgs { + /*id,*/ state: ids, + ui, + .. + } = args; + + let mut events = Vec::new(); + + if self.show.character_window { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 658.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(ids.social_frame, ui); + } else { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 25.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(ids.social_frame, ui); + } + + // X-Button + if Button::image(self.imgs.close_button) + .w_h(28.0, 28.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(ids.social_frame, 0.0, 0.0) + .set(ids.social_close, ui) + .was_clicked() + { + events.push(Event::Close); + } + + // Title + Text::new("Social") + .mid_top_with_margin_on(ids.social_frame, 6.0) + .font_id(self.fonts.metamorph) + .font_size(14) + .color(TEXT_COLOR) + .set(ids.social_title, ui); + + // Alignment + Rectangle::fill_with([99.0 * 4.0, 112.0 * 4.0], color::TRANSPARENT) + .mid_top_with_margin_on(ids.social_frame, 8.0 * 4.0) + .set(ids.align, ui); + // Content Alignment + Rectangle::fill_with([94.0 * 4.0, 94.0 * 4.0], color::TRANSPARENT) + .middle_of(ids.frame) + .scroll_kids() + .scroll_kids_vertically() + .set(ids.content_align, ui); + Scrollbar::y_axis(ids.content_align) + .thickness(5.0) + .rgba(0.33, 0.33, 0.33, 1.0) + .set(ids.scrollbar, ui); + // Frame + Image::new(self.imgs.social_frame) + .w_h(99.0 * 4.0, 100.0 * 4.0) + .mid_bottom_of(ids.align) + .set(ids.frame, ui); + + // Online Tab + + if Button::image(if let SocialTab::Online = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button + }) + .w_h(30.0 * 4.0, 12.0 * 4.0) + .hover_image(if let SocialTab::Online = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button_hover + }) + .press_image(if let SocialTab::Online = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button_press + }) + .top_left_with_margins_on(ids.align, 4.0, 0.0) + .label("Online") + .label_font_size(14) + .parent(ids.frame) + .label_color(TEXT_COLOR) + .set(ids.online_tab, ui) + .was_clicked() + { + events.push(Event::ChangeSocialTab(SocialTab::Online)); + } + + // Contents + + if let SocialTab::Online = self.show.social_tab { + // TODO Needs to be a string sent from the server + + // Players list + // TODO: this list changes infrequently enough that it should not have to be recreated every frame + let ecs = self.client.state().ecs(); + let players = ecs.read_storage::(); + let mut count = 0; + for player in players.join() { + if ids.player_names.len() <= count { + ids.update(|ids| { + ids.player_names + .resize(count + 1, &mut ui.widget_id_generator()) + }) + } + + Text::new(&player.alias) + .down_from(ids.online_title, count as f64 * (15.0 + 3.0)) + .font_size(15) + .font_id(self.fonts.opensans) + .color(TEXT_COLOR) + .set(ids.player_names[count], ui); + + count += 1; + } + Text::new(&format!("{} player(s) online\n", count)) + .top_left_with_margins_on(ids.content_align, -2.0, 7.0) + .font_size(14) + .font_id(self.fonts.opensans) + .color(TEXT_COLOR) + .set(ids.online_title, ui); + } + + // Friends Tab + + if Button::image(if let SocialTab::Friends = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button + }) + .w_h(30.0 * 4.0, 12.0 * 4.0) + .hover_image(if let SocialTab::Friends = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button + }) + .press_image(if let SocialTab::Friends = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button + }) + .right_from(ids.online_tab, 0.0) + .label("Friends") + .label_font_size(14) + .parent(ids.frame) + .label_color(TEXT_COLOR_3) + .set(ids.friends_tab, ui) + .was_clicked() + { + events.push(Event::ChangeSocialTab(SocialTab::Friends)); + } + + // Contents + + if let SocialTab::Friends = self.show.social_tab { + Text::new("Not yet available") + .middle_of(ids.content_align) + .font_size(18) + .font_id(self.fonts.opensans) + .color(TEXT_COLOR_3) + .set(ids.friends_test, ui); + } + + // Faction Tab + let button_img = if let SocialTab::Faction = self.show.social_tab { + self.imgs.social_button_pressed + } else { + self.imgs.social_button + }; + if Button::image(button_img) + .w_h(30.0 * 4.0, 12.0 * 4.0) + .right_from(ids.friends_tab, 0.0) + .label("Faction") + .parent(ids.frame) + .label_font_size(14) + .label_color(TEXT_COLOR_3) + .set(ids.faction_tab, ui) + .was_clicked() + { + events.push(Event::ChangeSocialTab(SocialTab::Faction)); + } + + // Contents + + if let SocialTab::Faction = self.show.social_tab { + Text::new("Not yet available") + .middle_of(ids.content_align) + .font_size(18) + .font_id(self.fonts.opensans) + .color(TEXT_COLOR_3) + .set(ids.faction_test, ui); + } + + events + } +} diff --git a/voxygen/src/hud/spell.rs b/voxygen/src/hud/spell.rs new file mode 100644 index 0000000000..2802e86d86 --- /dev/null +++ b/voxygen/src/hud/spell.rs @@ -0,0 +1,117 @@ +use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR}; +use conrod_core::{ + color, + widget::{self, Button, Image, Rectangle, Text}, + widget_ids, /*, Color*/ + Colorable, Positionable, Sizeable, Widget, WidgetCommon, +}; + +use client::{self, Client}; + +widget_ids! { + pub struct Ids { + spell_frame, + spell_close, + spell_title, + frame, + content_align, + + + + } +} + +#[derive(WidgetCommon)] +pub struct Spell<'a> { + _show: &'a Show, + _client: &'a Client, + + imgs: &'a Imgs, + fonts: &'a Fonts, + #[conrod(common_builder)] + common: widget::CommonBuilder, +} + +impl<'a> Spell<'a> { + pub fn new(show: &'a Show, _client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self { + Self { + _show: show, + imgs, + _client, + fonts: fonts, + common: widget::CommonBuilder::default(), + } + } +} + +/*pub struct State { + ids: Ids, +}*/ + +pub enum Event { + Close, +} + +impl<'a> Widget for Spell<'a> { + type State = Ids; + type Style = (); + type Event = Option; + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + Ids::new(id_gen) + } + + fn style(&self) -> Self::Style { + () + } + + fn update(self, args: widget::UpdateArgs) -> Self::Event { + let widget::UpdateArgs { + id: _, state, ui, .. + } = args; + + if self._show.character_window { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 658.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(state.spell_frame, ui); + } else { + Image::new(self.imgs.window_3) + .top_left_with_margins_on(ui.window, 200.0, 25.0) + .w_h(103.0 * 4.0, 122.0 * 4.0) + .set(state.spell_frame, ui); + } + + // X-Button + if Button::image(self.imgs.close_button) + .w_h(28.0, 28.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(state.spell_frame, 0.0, 0.0) + .set(state.spell_close, ui) + .was_clicked() + { + return Some(Event::Close); + } + + // Title + // TODO: Use an actual character name. + Text::new("Spell") + .mid_top_with_margin_on(state.spell_frame, 6.0) + .font_id(self.fonts.metamorph) + .font_size(14) + .color(TEXT_COLOR) + .set(state.spell_title, ui); + + // Content Alignment + Rectangle::fill_with([95.0 * 4.0, 108.0 * 4.0], color::TRANSPARENT) + .mid_top_with_margin_on(state.spell_frame, 40.0) + .set(state.content_align, ui); + + // Contents + + // Frame + + None + } +}