From d6b38c8cd227791d2ca2c532710a28210535234a Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 31 May 2020 14:50:57 -0400 Subject: [PATCH] More main menu work, split main menu ui into multiple modules, misc fixes in the renderer --- voxygen/src/menu/main/ui/connecting.rs | 36 ++ voxygen/src/menu/main/ui/login.rs | 237 ++++++++ voxygen/src/menu/main/{ui.rs => ui/mod.rs} | 535 +++++++----------- voxygen/src/ui/ice/component/mod.rs | 1 + voxygen/src/ui/ice/component/neat_button.rs | 50 +- voxygen/src/ui/ice/renderer/mod.rs | 4 +- voxygen/src/ui/ice/renderer/widget/text.rs | 7 + .../src/ui/ice/renderer/widget/text_input.rs | 2 +- 8 files changed, 505 insertions(+), 367 deletions(-) create mode 100644 voxygen/src/menu/main/ui/connecting.rs create mode 100644 voxygen/src/menu/main/ui/login.rs rename voxygen/src/menu/main/{ui.rs => ui/mod.rs} (79%) diff --git a/voxygen/src/menu/main/ui/connecting.rs b/voxygen/src/menu/main/ui/connecting.rs new file mode 100644 index 0000000000..4297ba4035 --- /dev/null +++ b/voxygen/src/menu/main/ui/connecting.rs @@ -0,0 +1,36 @@ +use super::{IcedImgs as Imgs, Message}; +use crate::{ + i18n::Localization, + ui::ice::{ + component::neat_button, + widget::{image, BackgroundContainer, Image}, + Element, + }, +}; +use iced::{button, Length, Space}; + +/// Connecting screen for the main menu +pub struct Screen { + cancel_button: button::State, +} + +impl Screen { + pub fn new() -> Self { + Self { + cancel_button: Default::default(), + } + } + + pub(super) fn view( + &mut self, + imgs: &Imgs, + bg_img: image::Handle, + start: &std::time::Instant, + i18n: &Localization, + ) -> Element { + let content = Space::new(Length::Fill, Length::Fill); + // Note: could replace this with styling on iced's container since we aren't + // using fixed aspect ratio + BackgroundContainer::new(Image::new(bg_img), content).into() + } +} diff --git a/voxygen/src/menu/main/ui/login.rs b/voxygen/src/menu/main/ui/login.rs new file mode 100644 index 0000000000..de21d09597 --- /dev/null +++ b/voxygen/src/menu/main/ui/login.rs @@ -0,0 +1,237 @@ +use super::{IcedImgs as Imgs, LoginInfo, Message}; +use crate::{ + i18n::Localization, + ui::ice::{ + component::neat_button, + widget::{ + compound_graphic::{CompoundGraphic, Graphic}, + BackgroundContainer, Image, Padding, + }, + ButtonStyle, Element, + }, +}; +use iced::{button, text_input, Align, Column, Container, Length, Row, Space, TextInput}; +use vek::*; + +const TEXT_COLOR: iced::Color = iced::Color::from_rgb(1.0, 1.0, 1.0); +const DISABLED_TEXT_COLOR: iced::Color = iced::Color::from_rgba(1.0, 1.0, 1.0, 0.2); +const FILL_FRAC_ONE: f32 = 0.77; +const FILL_FRAC_TWO: f32 = 0.53; +const INPUT_WIDTH: u16 = 250; +const INPUT_TEXT_SIZE: u16 = 24; + +/// Login screen for the main menu +pub struct Screen { + quit_button: button::State, + settings_button: button::State, + servers_button: button::State, + + pub banner: Banner, +} + +impl Screen { + pub fn new() -> Self { + Self { + servers_button: Default::default(), + settings_button: Default::default(), + quit_button: Default::default(), + + banner: Banner::new(), + } + } + + pub(super) fn view( + &mut self, + imgs: &Imgs, + login_info: &LoginInfo, + i18n: &Localization, + ) -> Element { + let button_style = ButtonStyle::new(imgs.button) + .hover_image(imgs.button_hover) + .press_image(imgs.button_press) + .text_color(TEXT_COLOR) + .disabled_text_color(DISABLED_TEXT_COLOR); + + let buttons = Column::with_children(vec![ + neat_button( + &mut self.servers_button, + i18n.get("common.servers"), + FILL_FRAC_ONE, + button_style, + Some(Message::ShowServers), + ), + neat_button( + &mut self.settings_button, + i18n.get("common.settings"), + FILL_FRAC_ONE, + button_style, + None, + ), + neat_button( + &mut self.quit_button, + i18n.get("common.quit"), + FILL_FRAC_ONE, + button_style, + Some(Message::Quit), + ), + ]) + .width(Length::Fill) + .max_width(200) + .spacing(5) + .padding(10); + + let buttons = Container::new(buttons) + .width(Length::Fill) + .height(Length::Fill) + .align_y(Align::End) + .padding(20); + + let banner = self.banner.view(imgs, login_info, i18n, button_style); + + let central_column = Container::new(banner) + .width(Length::Fill) + .height(Length::Fill) + .align_x(Align::Center) + .align_y(Align::Center); + + let image3 = Image::new(imgs.banner_bottom).fix_aspect_ratio(); + + let content = + Row::with_children(vec![buttons.into(), central_column.into(), image3.into()]) + .width(Length::Fill) + .height(Length::Fill) + .spacing(10); + + BackgroundContainer::new(Image::new(imgs.bg), content).into() + } +} + +pub struct Banner { + pub username: text_input::State, + pub password: text_input::State, + pub server: text_input::State, + + multiplayer_button: button::State, + #[cfg(feature = "singleplayer")] + singleplayer_button: button::State, +} + +impl Banner { + fn new() -> Self { + Self { + username: Default::default(), + password: Default::default(), + server: Default::default(), + + multiplayer_button: Default::default(), + #[cfg(feature = "singleplayer")] + singleplayer_button: Default::default(), + } + } + + fn view( + &mut self, + imgs: &Imgs, + login_info: &LoginInfo, + i18n: &Localization, + button_style: ButtonStyle, + ) -> Element { + let banner_content = Column::with_children(vec![ + Image::new(imgs.v_logo) + .fix_aspect_ratio() + .height(Length::FillPortion(20)) + .into(), + Space::new(Length::Fill, Length::FillPortion(5)).into(), + Column::with_children(vec![ + BackgroundContainer::new( + Image::new(imgs.input_bg) + .width(Length::Units(INPUT_WIDTH)) + .fix_aspect_ratio(), + TextInput::new( + &mut self.username, + "Username", + &login_info.username, + Message::Username, + ) + .size(INPUT_TEXT_SIZE) + .on_submit(Message::FocusPassword), + ) + .padding(Padding::new().horizontal(10).top(10)) + .into(), + BackgroundContainer::new( + Image::new(imgs.input_bg) + .width(Length::Units(INPUT_WIDTH)) + .fix_aspect_ratio(), + TextInput::new( + &mut self.password, + "Password", + &login_info.password, + Message::Password, + ) + .size(INPUT_TEXT_SIZE) + .password() + .on_submit(Message::Multiplayer), + ) + .padding(Padding::new().horizontal(10).top(8)) + .into(), + BackgroundContainer::new( + Image::new(imgs.input_bg) + .width(Length::Units(INPUT_WIDTH)) + .fix_aspect_ratio(), + TextInput::new( + &mut self.server, + "Server", + &login_info.server, + Message::Server, + ) + .size(INPUT_TEXT_SIZE) + .on_submit(Message::Multiplayer), + ) + .padding(Padding::new().horizontal(10).top(8)) + .into(), + ]) + .spacing(2) + .height(Length::FillPortion(50)) + .into(), + Column::with_children(vec![ + neat_button( + &mut self.multiplayer_button, + i18n.get("common.multiplayer"), + FILL_FRAC_TWO, + button_style, + Some(Message::Multiplayer), + ), + #[cfg(feature = "singleplayer")] + neat_button( + &mut self.singleplayer_button, + i18n.get("common.singleplayer"), + FILL_FRAC_TWO, + button_style, + Some(Message::Singleplayer), + ), + ]) + .max_width(240) + .spacing(8) + .into(), + ]) + .width(Length::Fill) + .height(Length::Fill) + .align_items(Align::Center); + + let banner = BackgroundContainer::new( + CompoundGraphic::from_graphics(vec![ + Graphic::image(imgs.banner_top, [138, 17], [0, 0]), + Graphic::rect(Rgba::new(0, 0, 0, 230), [130, 195], [4, 17]), + Graphic::image(imgs.banner, [130, 15], [4, 212]) + .color(Rgba::new(255, 255, 255, 230)), + ]) + .fix_aspect_ratio() + .height(Length::Fill), + banner_content, + ) + .padding(Padding::new().horizontal(16).vertical(20)) + .max_width(330); + + banner.into() + } +} diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui/mod.rs similarity index 79% rename from voxygen/src/menu/main/ui.rs rename to voxygen/src/menu/main/ui/mod.rs index 6c7719b13a..43d363c573 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui/mod.rs @@ -1,3 +1,6 @@ +mod connecting; +mod login; + use crate::{ i18n::{i18n_asset_key, Localization}, render::Renderer, @@ -22,6 +25,7 @@ use conrod_core::{ use image::DynamicImage; use rand::{seq::SliceRandom, thread_rng, Rng}; use std::time::Duration; +use ui::ice::widget; const COL1: Color = Color::Rgba(0.07, 0.1, 0.1, 0.9); @@ -29,6 +33,194 @@ const COL1: Color = Color::Rgba(0.07, 0.1, 0.1, 0.9); /*const UI_MAIN: Color = Color::Rgba(0.61, 0.70, 0.70, 1.0); // Greenish Blue const UI_HIGHLIGHT_0: Color = Color::Rgba(0.79, 1.09, 1.09, 1.0);*/ +use iced::text_input; +image_ids_ice! { + struct IcedImgs { + + v_logo: "voxygen.element.v_logo", + + info_frame: "voxygen.element.frames.info_frame_2", + + //banner: "voxygen.element.frames.banner", + + bg: "voxygen.background.bg_main", + banner: "voxygen.element.frames.banner_png", + banner_bottom: "voxygen.element.frames.banner_bottom_png", + banner_top: "voxygen.element.frames.banner_top", + button: "voxygen.element.buttons.button", + button_hover: "voxygen.element.buttons.button_hover", + button_press: "voxygen.element.buttons.button_press", + input_bg: "voxygen.element.misc_bg.textbox", + disclaimer: "voxygen.element.frames.disclaimer", + loading_art: "voxygen.element.frames.loading_screen.loading_bg", + loading_art_l: "voxygen.element.frames.loading_screen.loading_bg_l", + loading_art_r: "voxygen.element.frames.loading_screen.loading_bg_r", + + + nothing: (), + } +} + +// Randomly loaded background images +const BG_IMGS: [&str; 16] = [ + "voxygen.background.bg_1", + "voxygen.background.bg_2", + "voxygen.background.bg_3", + "voxygen.background.bg_4", + "voxygen.background.bg_5", + "voxygen.background.bg_6", + "voxygen.background.bg_7", + "voxygen.background.bg_8", + "voxygen.background.bg_9", + //"voxygen.background.bg_10", + "voxygen.background.bg_11", + //"voxygen.background.bg_12", + "voxygen.background.bg_13", + //"voxygen.background.bg_14", + "voxygen.background.bg_15", + "voxygen.background.bg_16", +]; + +pub enum Event { + LoginAttempt { + username: String, + password: String, + server_address: String, + }, + CancelLoginAttempt, + #[cfg(feature = "singleplayer")] + StartSingleplayer, + Quit, + Settings, + //DisclaimerClosed, + AuthServerTrust(String, bool), +} + +pub enum PopupType { + Error, + ConnectionInfo, + AuthTrustPrompt(String), +} + +pub struct PopupData { + msg: String, + popup_type: PopupType, +} + +pub struct LoginInfo { + pub username: String, + pub password: String, + pub server: String, +} + +enum Screen { + Login { + screen: login::Screen, + }, + Connecting { + screen: connecting::Screen, + // TODO: why instant? + start: std::time::Instant, + }, +} + +// TODO: use i18n font scale thing +struct IcedState { + imgs: IcedImgs, + bg_img: widget::image::Handle, + i18n: std::sync::Arc, + + // TODO: not sure if this should be used for connecting + popup: Option, + show_servers: bool, + show_disclaimer: bool, + login_info: LoginInfo, + + screen: Screen, +} + +#[derive(Clone)] +enum Message { + Quit, + ShowServers, + #[cfg(feature = "singleplayer")] + Singleplayer, + Multiplayer, + Username(String), + Password(String), + Server(String), + FocusPassword, +} + +impl IcedState { + fn new( + imgs: IcedImgs, + bg_img: widget::image::Handle, + i18n: std::sync::Arc, + ) -> Self { + Self { + imgs, + bg_img, + i18n, + popup: None, + show_servers: false, + show_disclaimer: false, + login_info: LoginInfo { + username: String::new(), + password: String::new(), + server: String::new(), + }, + + screen: Screen::Login { + screen: login::Screen::new(), + }, + } + } + + fn view(&mut self) -> Element { + match &mut self.screen { + Screen::Login { screen } => screen.view(&self.imgs, &self.login_info, &self.i18n), + Screen::Connecting { screen, start } => { + screen.view(&self.imgs, self.bg_img, &start, &self.i18n) + }, + } + } + + fn update(&mut self, message: Message, events: &mut Vec) { + match message { + Message::Quit => events.push(Event::Quit), + Message::ShowServers => self.show_servers = true, + #[cfg(feature = "singleplayer")] + Message::Singleplayer => events.push(Event::StartSingleplayer), + Message::Multiplayer => { + self.screen = Screen::Connecting { + screen: connecting::Screen::new(), + start: std::time::Instant::now(), + }; + self.popup = Some(PopupData { + msg: [self.i18n.get("main.connecting"), "..."].concat(), + popup_type: PopupType::ConnectionInfo, + }); + + events.push(Event::LoginAttempt { + username: self.login_info.username.clone(), + password: self.login_info.password.clone(), + server_address: self.login_info.server.clone(), + }); + }, + Message::Username(new_value) => self.login_info.username = new_value, + Message::Password(new_value) => self.login_info.password = new_value, + Message::Server(new_value) => self.login_info.server = new_value, + Message::FocusPassword => { + if let Screen::Login { screen } = &mut self.screen { + screen.banner.password = text_input::State::focused(); + screen.banner.username = text_input::State::new(); + } + }, + } + } +} + widget_ids! { struct Ids { // Background and logo @@ -38,7 +230,6 @@ widget_ids! { alpha_text, banner, banner_top, - gears, // Disclaimer //disc_window, //disc_text_1, @@ -82,13 +273,6 @@ widget_ids! { info_bottom, // Auth Trust Prompt button_add_auth_trust, - // Loading Screen Tips - tip_txt_bg, - tip_txt, - // Loading Screen Artwork - mid, - left, - right, } } @@ -109,39 +293,7 @@ image_ids! { button_press: "voxygen.element.buttons.button_press", input_bg: "voxygen.element.misc_bg.textbox", //disclaimer: "voxygen.element.frames.disclaimer", - loading_art: "voxygen.element.frames.loading_screen.loading_bg", - loading_art_l: "voxygen.element.frames.loading_screen.loading_bg_l", - loading_art_r: "voxygen.element.frames.loading_screen.loading_bg_r", - // Animation - f1: "voxygen.element.animation.gears.1", - f2: "voxygen.element.animation.gears.2", - f3: "voxygen.element.animation.gears.3", - f4: "voxygen.element.animation.gears.4", - f5: "voxygen.element.animation.gears.5", - - nothing: (), - } -} - -image_ids_ice! { - struct IcedImgs { - - v_logo: "voxygen.element.v_logo", - - info_frame: "voxygen.element.frames.info_frame_2", - - //banner: "voxygen.element.frames.banner", - - bg: "voxygen.background.bg_main", - banner: "voxygen.element.frames.banner_png", - banner_bottom: "voxygen.element.frames.banner_bottom_png", - banner_top: "voxygen.element.frames.banner_top", - button: "voxygen.element.buttons.button", - button_hover: "voxygen.element.buttons.button_hover", - button_press: "voxygen.element.buttons.button_press", - input_bg: "voxygen.element.misc_bg.textbox", - disclaimer: "voxygen.element.frames.disclaimer", nothing: (), @@ -150,7 +302,7 @@ image_ids_ice! { rotation_image_ids! { pub struct ImgsRot { - + // Tooltip Test tt_side: "voxygen/element/frames/tt_test_edge", @@ -158,267 +310,6 @@ rotation_image_ids! { } } -pub enum Event { - LoginAttempt { - username: String, - password: String, - server_address: String, - }, - CancelLoginAttempt, - #[cfg(feature = "singleplayer")] - StartSingleplayer, - Quit, - Settings, - //DisclaimerClosed, - AuthServerTrust(String, bool), -} - -pub enum PopupType { - Error, - ConnectionInfo, - AuthTrustPrompt(String), -} - -pub struct PopupData { - msg: String, - popup_type: PopupType, -} - -use ui::ice::component::neat_button; -struct IcedState { - imgs: IcedImgs, - quit_button: neat_button::State, - settings_button: neat_button::State, - servers_button: neat_button::State, - multiplayer_button: neat_button::State, - #[cfg(feature = "singleplayer")] - singleplayer_button: neat_button::State, - username_input: iced::text_input::State, - password_input: iced::text_input::State, - server_input: iced::text_input::State, - username_value: String, - password_value: String, - server_value: String, - show_servers: bool, -} - -#[derive(Clone)] // TODO: why does iced require Clone? -enum Message { - Quit, - ShowServers, - #[cfg(feature = "singleplayer")] - Singleplayer, - Multiplayer, - Username(String), - Password(String), - Server(String), - FocusPassword, -} - -impl IcedState { - pub fn new(imgs: IcedImgs) -> Self { - Self { - imgs, - servers_button: Default::default(), - settings_button: Default::default(), - quit_button: Default::default(), - multiplayer_button: Default::default(), - #[cfg(feature = "singleplayer")] - singleplayer_button: Default::default(), - username_input: Default::default(), - password_input: Default::default(), - server_input: Default::default(), - username_value: String::new(), - password_value: String::new(), - server_value: String::new(), - show_servers: false, - } - } - - pub fn view(&mut self, i18n: &Localization) -> Element { - //let button_font_size = 30; - const TEXT_COLOR: iced::Color = iced::Color::from_rgb(1.0, 1.0, 1.0); - const DISABLED_TEXT_COLOR: iced::Color = iced::Color::from_rgba(1.0, 1.0, 1.0, 0.2); - const FILL_FRAC_ONE: f32 = 0.77; - const FILL_FRAC_TWO: f32 = 0.53; - - use iced::{Align, Column, Container, Length, Row, Space, TextInput}; - use ui::ice::{ - widget::{ - compound_graphic::{CompoundGraphic, Graphic}, - BackgroundContainer, Image, Padding, - }, - ButtonStyle, - }; - use vek::*; - - let button_style = ButtonStyle::new(self.imgs.button) - .hover_image(self.imgs.button_hover) - .press_image(self.imgs.button_press) - .text_color(TEXT_COLOR) - .disabled_text_color(DISABLED_TEXT_COLOR); - - let buttons = Column::with_children(vec![ - self.servers_button.view( - i18n.get("common.servers"), - FILL_FRAC_ONE, - button_style, - Some(Message::ShowServers), - ), - self.settings_button.view( - i18n.get("common.settings"), - FILL_FRAC_ONE, - button_style, - None, - ), - self.quit_button.view( - i18n.get("common.quit"), - FILL_FRAC_ONE, - button_style, - Some(Message::Quit), - ), - ]) - .width(Length::Fill) - .max_width(200) - .spacing(5) - .padding(10); - - let buttons = Container::new(buttons) - .width(Length::Fill) - .height(Length::Fill) - .align_y(Align::End) - .padding(20); - const INPUT_WIDTH: u16 = 250; - const INPUT_TEXT_SIZE: u16 = 24; - let banner_content = Column::with_children(vec![ - Image::new(self.imgs.v_logo) - .fix_aspect_ratio() - .height(Length::FillPortion(20)) - .into(), - Space::new(Length::Fill, Length::FillPortion(5)).into(), - Column::with_children(vec![ - BackgroundContainer::new( - Image::new(self.imgs.input_bg) - .width(Length::Units(INPUT_WIDTH)) - .fix_aspect_ratio(), - TextInput::new( - &mut self.username_input, - "Username", - &self.username_value, - Message::Username, - ) - .size(INPUT_TEXT_SIZE) - .on_submit(Message::FocusPassword), - ) - .padding(Padding::new().horizontal(10).top(10)) - .into(), - BackgroundContainer::new( - Image::new(self.imgs.input_bg) - .width(Length::Units(INPUT_WIDTH)) - .fix_aspect_ratio(), - TextInput::new( - &mut self.password_input, - "Password", - &self.password_value, - Message::Password, - ) - .size(INPUT_TEXT_SIZE) - .password() - .on_submit(Message::Multiplayer), - ) - .padding(Padding::new().horizontal(10).top(8)) - .into(), - BackgroundContainer::new( - Image::new(self.imgs.input_bg) - .width(Length::Units(INPUT_WIDTH)) - .fix_aspect_ratio(), - TextInput::new( - &mut self.server_input, - "Server", - &self.server_value, - Message::Server, - ) - .size(INPUT_TEXT_SIZE) - .on_submit(Message::Multiplayer), - ) - .padding(Padding::new().horizontal(10).top(8)) - .into(), - ]) - .spacing(2) - .height(Length::FillPortion(50)) - .into(), - Column::with_children(vec![ - self.multiplayer_button.view( - i18n.get("common.multiplayer"), - FILL_FRAC_TWO, - button_style, - Some(Message::Multiplayer), - ), - #[cfg(feature = "singleplayer")] - self.singleplayer_button.view( - i18n.get("common.singleplayer"), - FILL_FRAC_TWO, - button_style, - Some(Message::Singleplayer), - ), - ]) - .max_width(240) - .spacing(8) // TODO scale with available window size, awkward because both width and height can become limiting factors, might need custom column, could also just use fill portion - .into(), - ]) - .width(Length::Fill) - .height(Length::Fill) - .align_items(Align::Center); - - let banner = BackgroundContainer::new( - CompoundGraphic::from_graphics(vec![ - Graphic::image(self.imgs.banner_top, [138, 17], [0, 0]), - Graphic::rect(Rgba::new(0, 0, 0, 230), [130, 195], [4, 17]), - Graphic::image(self.imgs.banner, [130, 15], [4, 212]) - .color(Rgba::new(255, 255, 255, 230)), - ]) - .fix_aspect_ratio() - .height(Length::Fill), - banner_content, - ) - .padding(Padding::new().horizontal(16).vertical(20)) - .max_width(330); - - let central_column = Container::new(banner) - .width(Length::Fill) - .height(Length::Fill) - .align_x(Align::Center) - .align_y(Align::Center); - - let image3 = Image::new(self.imgs.banner_bottom).fix_aspect_ratio(); - - let content = - Row::with_children(vec![buttons.into(), central_column.into(), image3.into()]) - .width(Length::Fill) - .height(Length::Fill) - .spacing(10); - - BackgroundContainer::new(Image::new(self.imgs.bg), content).into() - } - - pub fn update(&mut self, message: Message, events: &mut Vec) { - match message { - Message::Quit => events.push(Event::Quit), - Message::ShowServers => self.show_servers = true, - #[cfg(feature = "singleplayer")] - Message::Singleplayer => events.push(Event::StartSingleplayer), - Message::Multiplayer => (), //TODO - Message::Username(new_value) => self.username_value = new_value, - Message::Password(new_value) => self.password_value = new_value, - Message::Server(new_value) => self.server_value = new_value, - Message::FocusPassword => { - self.password_input = iced::text_input::State::focused(); - self.username_input = iced::text_input::State::new(); - }, - } - } -} - pub struct MainMenuUi { ui: Ui, ice_ui: IcedUi, @@ -448,26 +339,6 @@ impl<'a> MainMenuUi { let window = &mut global_state.window; let networking = &global_state.settings.networking; let gameplay = &global_state.settings.gameplay; - // Randomly loaded background images - let bg_imgs = [ - "voxygen.background.bg_1", - "voxygen.background.bg_2", - "voxygen.background.bg_3", - "voxygen.background.bg_4", - "voxygen.background.bg_5", - "voxygen.background.bg_6", - "voxygen.background.bg_7", - "voxygen.background.bg_8", - "voxygen.background.bg_9", - //"voxygen.background.bg_10", - "voxygen.background.bg_11", - //"voxygen.background.bg_12", - "voxygen.background.bg_13", - //"voxygen.background.bg_14", - "voxygen.background.bg_15", - "voxygen.background.bg_16", - ]; - let mut rng = thread_rng(); let mut ui = Ui::new(window).unwrap(); ui.set_scaling_mode(gameplay.ui_scale); @@ -476,11 +347,8 @@ impl<'a> MainMenuUi { // Load images let imgs = Imgs::load(&mut ui).expect("Failed to load images"); let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load images!"); - let bg_img_id = ui.add_graphic(Graphic::Image( - DynamicImage::load_expect(bg_imgs.choose(&mut rng).unwrap()), - None, - )); - //let chosen_tip = *tips.choose(&mut rng).unwrap(); + let bg_img_spec = BG_IMGS.choose(&mut thread_rng()).unwrap(); + let bg_img_id = ui.add_graphic(Graphic::Image(DynamicImage::load_expect(bg_img_spec))); // Load language let i18n = Localization::load_expect(&i18n_asset_key( &global_state.settings.language.selected_language, @@ -502,7 +370,11 @@ impl<'a> MainMenuUi { }; let mut ice_ui = IcedUi::new(window, ice_font).unwrap(); - let ice_state = IcedState::new(IcedImgs::load(&mut ice_ui).expect("Failed to load images")); + let ice_state = IcedState::new( + IcedImgs::load(&mut ice_ui).expect("Failed to load images"), + ice_ui.add_graphic(Graphic::Image(load_expect(bg_img_spec))), + i18n.clone(), + ); Self { ui, @@ -1188,10 +1060,9 @@ impl<'a> MainMenuUi { pub fn maintain(&mut self, global_state: &mut GlobalState, dt: Duration) -> Vec { let mut events = self.update_layout(global_state, dt); self.ui.maintain(global_state.window.renderer_mut(), None); - let (messages, _) = self.ice_ui.maintain( - self.ice_state.view(&self.i18n), - global_state.window.renderer_mut(), - ); + let (messages, _) = self + .ice_ui + .maintain(self.ice_state.view(), global_state.window.renderer_mut()); messages .into_iter() .for_each(|message| self.ice_state.update(message, &mut events)); diff --git a/voxygen/src/ui/ice/component/mod.rs b/voxygen/src/ui/ice/component/mod.rs index 7f44faef0b..de0a8293eb 100644 --- a/voxygen/src/ui/ice/component/mod.rs +++ b/voxygen/src/ui/ice/component/mod.rs @@ -1 +1,2 @@ pub mod neat_button; +pub use neat_button::neat_button; diff --git a/voxygen/src/ui/ice/component/neat_button.rs b/voxygen/src/ui/ice/component/neat_button.rs index f0ce7d576c..6b68988b46 100644 --- a/voxygen/src/ui/ice/component/neat_button.rs +++ b/voxygen/src/ui/ice/component/neat_button.rs @@ -1,44 +1,32 @@ use crate::ui::ice as ui; -use iced::{Button, Element, Length}; +use iced::{button::State, Button, Element, Length}; use ui::{ widget::{AspectRatioContainer, FillText}, ButtonStyle, }; -#[derive(Default)] -pub struct State { - state: iced::button::State, -} - -impl State { - pub fn new() -> Self { Self::default() } - - pub fn view( - &mut self, - label: impl Into, - fill_fraction: f32, - button_style: ButtonStyle, - message: Option, - ) -> Element { - let button = Button::new( - &mut self.state, - FillText::new(label).fill_fraction(fill_fraction), - ) +pub fn neat_button( + state: &mut State, + label: impl Into, + fill_fraction: f32, + button_style: ButtonStyle, + message: Option, +) -> Element { + let button = Button::new(state, FillText::new(label).fill_fraction(fill_fraction)) .height(Length::Fill) .width(Length::Fill) .style(button_style); - let button = match message { - Some(message) => button.on_press(message), - None => button, - }; + let button = match message { + Some(message) => button.on_press(message), + None => button, + }; - let container = AspectRatioContainer::new(button); - let container = match button_style.active().0 { - Some(img) => container.ratio_of_image(img), - None => container, - }; + let container = AspectRatioContainer::new(button); + let container = match button_style.active().0 { + Some(img) => container.ratio_of_image(img), + None => container, + }; - container.into() - } + container.into() } diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 2812b98c3c..a7fdd24645 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -446,7 +446,7 @@ impl IcedRenderer { }, Primitive::Text { glyphs, - bounds, // iced::Rectangle + bounds: _bounds, // iced::Rectangle linear_color, /*font, *horizontal_alignment, @@ -505,8 +505,6 @@ impl IcedRenderer { }, Primitive::Clip { bounds, content } => { let new_scissor = { - let min_x = bounds.x; - let min_y = bounds.y; let intersection = Aabr { min: Vec2 { x: (bounds.x * self.p_scale) as u16, diff --git a/voxygen/src/ui/ice/renderer/widget/text.rs b/voxygen/src/ui/ice/renderer/widget/text.rs index d9f6b1629e..9caf5c11c1 100644 --- a/voxygen/src/ui/ice/renderer/widget/text.rs +++ b/voxygen/src/ui/ice/renderer/widget/text.rs @@ -80,6 +80,13 @@ impl text::Renderer for IcedRenderer { .cache .glyph_cache_mut() .glyphs(section) + .filter(|g| { + !content[g.byte_index..] + .chars() + .next() + .unwrap() + .is_whitespace() + }) .cloned() .collect::>(); diff --git a/voxygen/src/ui/ice/renderer/widget/text_input.rs b/voxygen/src/ui/ice/renderer/widget/text_input.rs index 2d98756629..f267f7f451 100644 --- a/voxygen/src/ui/ice/renderer/widget/text_input.rs +++ b/voxygen/src/ui/ice/renderer/widget/text_input.rs @@ -37,7 +37,7 @@ impl text_input::Renderer for IcedRenderer { }; let mut glyph_calculator = self.cache.glyph_calculator(); - let mut width = glyph_calculator + let width = glyph_calculator .glyph_bounds(section) .map_or(0.0, |rect| rect.width() / p_scale);