add chat box, minimap buttons, ui windows, etc

Former-commit-id: 09d3e20b917a9ac9ef6333ee9bb913d01a7fb52c
This commit is contained in:
Imbris 2019-03-15 00:55:52 -04:00
parent 16ed207437
commit f837492284
111 changed files with 1787 additions and 492 deletions

124
voxygen/src/hud/chat.rs Normal file
View File

@ -0,0 +1,124 @@
use crate::ui::Ui;
use conrod_core::{
input::Key,
position::Dimension,
widget::{List, Rectangle, Text, TextEdit},
widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget,
};
use std::collections::VecDeque;
widget_ids! {
struct Ids {
message_box,
message_box_bg,
input,
input_bg,
}
}
// Consider making this a Widget
pub struct Chat {
ids: Ids,
messages: VecDeque<String>,
input: String,
new_messages: bool,
}
impl Chat {
pub fn new(ui: &mut Ui) -> Self {
Chat {
ids: Ids::new(ui.id_generator()),
messages: VecDeque::new(),
input: String::new(),
new_messages: false,
}
}
pub fn new_message(&mut self, msg: String) {
self.messages.push_back(msg);
self.new_messages = true;
}
// Determine if the message box is scrolled to the bottom
// (i.e. the player is viewing new messages)
// If so scroll down when new messages are added
fn scroll_new_messages(&mut self, ui_widgets: &mut UiCell) {
if let Some(scroll) = ui_widgets
.widget_graph()
.widget(self.ids.message_box)
.and_then(|widget| widget.maybe_y_scroll_state)
{
// If previously scrolled to the bottom stay there
if scroll.offset >= scroll.offset_bounds.start {
ui_widgets.scroll_widget(self.ids.message_box, [0.0, std::f64::MAX]);
}
}
}
pub fn update_layout(&mut self, ui_widgets: &mut UiCell) {
// If enter is pressed send the current message
if ui_widgets
.widget_input(self.ids.input)
.presses()
.key()
.any(|key_press| match key_press.key {
Key::Return => true,
_ => false,
})
{
self.new_message(self.input.clone());
// Scroll to the bottom
// TODO: uncomment when we can actually get chat messages from other people
//ui_widgets.scroll_widget(self.ids.message_box, [0.0, std::f64::MAX]);
self.input.clear();
}
// Maintain scrolling
if self.new_messages {
self.scroll_new_messages(ui_widgets);
self.new_messages = false;
}
// Chat input with rectangle as background
let text_edit = TextEdit::new(&self.input)
.w(500.0)
.restrict_to_height(false)
.font_size(30)
.bottom_left_with_margin_on(ui_widgets.window, 10.0);
let dims = match (
text_edit.get_x_dimension(ui_widgets),
text_edit.get_y_dimension(ui_widgets),
) {
(Dimension::Absolute(x), Dimension::Absolute(y)) => [x, y],
_ => [0.0, 0.0],
};
Rectangle::fill(dims)
.rgba(0.0, 0.0, 0.0, 0.8)
.x_position(text_edit.get_x_position(ui_widgets))
.y_position(text_edit.get_y_position(ui_widgets))
.set(self.ids.input_bg, ui_widgets);
if let Some(str) = text_edit.set(self.ids.input, ui_widgets) {
self.input = str.to_string();
self.input.retain(|c| c != '\n');
}
// Message box
Rectangle::fill([500.0, 90.0])
.rgba(0.0, 0.0, 0.0, 0.5)
.up_from(self.ids.input, 0.0)
.set(self.ids.message_box_bg, ui_widgets);
let (mut items, scrollbar) = List::flow_down(self.messages.len())
.middle_of(self.ids.message_box_bg)
// Why does scrollbar disappear when the list is the exact same height as its contents?
.scrollbar_next_to()
.scrollbar_thickness(20.0)
.scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
.set(self.ids.message_box, ui_widgets);
while let Some(item) = items.next(ui_widgets) {
item.set(
Text::new(&self.messages[item.i])
.font_size(30)
.rgba(1.0, 1.0, 1.0, 1.0),
ui_widgets,
)
}
if let Some(s) = scrollbar {
s.set(ui_widgets)
}
}
}

1214
voxygen/src/hud/mod.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
#![feature(drain_filter)]
#![recursion_limit="2048"]
pub mod anim;
pub mod error;
pub mod hud;
pub mod key_state;
pub mod menu;
pub mod mesh;

View File

@ -1,19 +1,14 @@
mod ui;
use std::time::Duration;
use vek::*;
use common::clock::Clock;
use crate::{
PlayState,
PlayStateResult,
GlobalState,
window::{
Event,
Window,
},
session::SessionState,
window::{Event, Window},
GlobalState, PlayState, PlayStateResult,
};
use common::clock::Clock;
use std::time::Duration;
use ui::MainMenuUi;
use vek::*;
const FPS: u64 = 60;
@ -25,18 +20,21 @@ impl MainMenuState {
/// Create a new `MainMenuState`
pub fn new(window: &mut Window) -> Self {
Self {
main_menu_ui: MainMenuUi::new(window)
main_menu_ui: MainMenuUi::new(window),
}
}
}
// The background colour
const BG_COLOR: Rgba<f32> = Rgba { r: 0.0, g: 0.3, b: 1.0, a: 1.0 };
// Background colour
const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0,
g: 0.3,
b: 1.0,
a: 1.0,
};
impl PlayState for MainMenuState {
fn play(&mut self, global_state: &mut GlobalState) -> PlayStateResult {
// Set up an fps clock
let mut clock = Clock::new();
@ -50,14 +48,15 @@ impl PlayState for MainMenuState {
self.main_menu_ui.handle_event(input);
}
// Ignore all other events
_ => {},
_ => {}
}
}
global_state.window.renderer_mut().clear(BG_COLOR);
// Maintain the UI
self.main_menu_ui.maintain(global_state.window.renderer_mut());
self.main_menu_ui
.maintain(global_state.window.renderer_mut());
// Check if there should be a login attempt
if let Some((username, address)) = self.main_menu_ui.login_attempt() {
// For now just start a new session
@ -71,15 +70,17 @@ impl PlayState for MainMenuState {
// Finish the frame
global_state.window.renderer_mut().flush();
global_state.window
global_state
.window
.swap_buffers()
.expect("Failed to swap window buffers");
// Wait for the next tick
clock.tick(Duration::from_millis(1000 / FPS));
}
}
fn name(&self) -> &'static str { "Title" }
fn name(&self) -> &'static str {
"Title"
}
}

View File

@ -1,34 +1,27 @@
use crate::{
render::Renderer,
ui::{ScaleMode, Ui},
window::Window,
Error, GlobalState, PlayState, PlayStateResult,
};
use conrod_core::{
Positionable,
Sizeable,
Widget,
Labelable,
Colorable,
Borderable,
widget_ids,
color::TRANSPARENT,
event::Input,
image::Id as ImgId,
text::font::Id as FontId,
widget::{
Image,
Button,
Canvas,
TextBox,
text_box::Event as TextBoxEvent,
}
};
use crate::{
window::Window,
render::Renderer,
ui::{Ui, ScaleMode}
widget::{text_box::Event as TextBoxEvent, Button, Canvas, Image, TextBox},
widget_ids, Borderable, Color,
Color::Rgba,
Colorable, Labelable, Positionable, Sizeable, Widget,
};
widget_ids!{
widget_ids! {
struct Ids {
// Background and logo
bg,
v_logo,
// Login
alpha_version,
// Login, Singleplayer
login_button,
login_text,
address_text,
@ -37,6 +30,8 @@ widget_ids!{
username_text,
username_bg,
username_field,
singleplayer_button,
singleplayer_text,
// Buttons
servers_button,
servers_text,
@ -50,6 +45,7 @@ widget_ids!{
struct Imgs {
bg: ImgId,
v_logo: ImgId,
alpha_version: ImgId,
address_text: ImgId,
username_text: ImgId,
@ -59,6 +55,7 @@ struct Imgs {
login_button: ImgId,
login_button_hover: ImgId,
login_button_press: ImgId,
singleplayer_text: ImgId,
servers_text: ImgId,
settings_text: ImgId,
@ -70,12 +67,21 @@ struct Imgs {
impl Imgs {
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
let mut load = |filename| {
let image = image::open(&[env!("CARGO_MANIFEST_DIR"), "/test_assets/ui/main/", filename].concat()).unwrap();
let image = image::open(
&[
env!("CARGO_MANIFEST_DIR"),
"/test_assets/ui/main/",
filename,
]
.concat(),
)
.unwrap();
ui.new_image(renderer, &image).unwrap()
};
Imgs {
bg: load("bg.png"),
v_logo: load("v_logo_a01.png"),
v_logo: load("v_logo.png"),
alpha_version: load("text/a01.png"),
// Input fields
address_text: load("text/server_address.png"),
@ -84,6 +90,7 @@ impl Imgs {
// Login button
login_text: load("text/login.png"),
singleplayer_text: load("text/singleplayer.png"),
login_button: load("buttons/button_login.png"),
login_button_hover: load("buttons/button_login_hover.png"),
login_button_press: load("buttons/button_login_press.png"),
@ -103,8 +110,9 @@ pub struct MainMenuUi {
ui: Ui,
ids: Ids,
imgs: Imgs,
font_id: FontId,
username: String,
font_metamorph: FontId,
font_whitney: FontId,
username: String,
server_address: String,
attempt_login: bool,
}
@ -118,17 +126,29 @@ impl MainMenuUi {
let ids = Ids::new(ui.id_generator());
// Load images
let imgs = Imgs::new(&mut ui, window.renderer_mut());
// Load font
let font_id = ui.new_font(conrod_core::text::font::from_file(
concat!(env!("CARGO_MANIFEST_DIR"), "/test_assets/font/Metamorphous-Regular.ttf")
).unwrap());
// Load fonts
let font_whitney = ui.new_font(
conrod_core::text::font::from_file(concat!(
env!("CARGO_MANIFEST_DIR"),
"/test_assets/font/Whitney-Book.ttf"
))
.unwrap(),
);
let font_metamorph = ui.new_font(
conrod_core::text::font::from_file(concat!(
env!("CARGO_MANIFEST_DIR"),
"/test_assets/font/Metamorphous-Regular.ttf"
))
.unwrap(),
);
Self {
ui,
imgs,
ids,
font_id,
username: "Username".to_string(),
server_address: "Server-Address".to_string(),
font_metamorph,
font_whitney,
username: "Username".to_string(),
server_address: "Server Address".to_string(),
attempt_login: false,
}
}
@ -145,13 +165,18 @@ impl MainMenuUi {
fn update_layout(&mut self) {
let ref mut ui_widgets = self.ui.set_widgets();
// Background image & Veloren logo
Image::new(self.imgs.bg)
.middle_of(ui_widgets.window)
.set(self.ids.bg, ui_widgets);
Image::new(self.imgs.v_logo)
// Background image, Veloren logo, Alpha-Version Label
Image::new(self.imgs.bg)
.middle_of(ui_widgets.window)
.set(self.ids.bg, ui_widgets);
Button::image(self.imgs.v_logo)
.w_h(346.0, 111.0)
.top_left_with_margins(30.0, 40.0)
.label("Alpha 0.1")
.label_rgba(255.0, 255.0, 255.0, 1.0)
.label_font_size(10)
.label_y(conrod_core::position::Relative::Scalar(-40.0))
.label_x(conrod_core::position::Relative::Scalar(-100.0))
.set(self.ids.v_logo, ui_widgets);
// Input fields
@ -159,65 +184,57 @@ impl MainMenuUi {
macro_rules! login {
() => {
self.attempt_login = true;
}
};
}
use conrod_core::color::TRANSPARENT;
// Username
// TODO: get a lower resolution and cleaner input_bg.png
Image::new(self.imgs.input_bg)
.w_h(672.0/2.0, 166.0/2.0)
.w_h(337.0, 67.0)
.middle_of(ui_widgets.window)
.set(self.ids.username_bg, ui_widgets);
Image::new(self.imgs.username_text)
.w_h(149.0, 24.0)
.up(0.0)
.align_left()
.set(self.ids.username_text, ui_widgets);
// TODO: figure out why cursor is rendered inconsistently
for event in TextBox::new(&self.username)
.w_h(580.0/2.0, 60.0/2.0)
.mid_bottom_with_margin_on(self.ids.username_bg, 44.0/2.0)
.w_h(580.0 / 2.0, 60.0 / 2.0)
.mid_bottom_with_margin_on(self.ids.username_bg, 44.0 / 2.0)
.font_size(20)
.font_id(self.font_whitney)
.text_color(Color::Rgba(220.0, 220.0, 220.0, 0.8))
// transparent background
.color(TRANSPARENT)
.border_color(TRANSPARENT)
.set(self.ids.username_field, ui_widgets)
{
match event {
TextBoxEvent::Update(username) => {
// Note: TextBox limits the input string length to what fits in it
self.username = username.to_string();
}
TextBoxEvent::Enter => login!(),
{
match event {
TextBoxEvent::Update(username) => {
// Note: TextBox limits the input string length to what fits in it
self.username = username.to_string();
}
TextBoxEvent::Enter => login!(),
}
}
// Server address
Image::new(self.imgs.address_text)
.w_h(227.0, 28.0)
.down_from(self.ids.username_bg, 10.0)
.align_left_of(self.ids.username_bg)
.set(self.ids.address_text, ui_widgets);
Image::new(self.imgs.input_bg)
.w_h(672.0/2.0, 166.0/2.0)
.down(0.0)
.align_left()
.w_h(337.0, 67.0)
.down_from(self.ids.username_bg, 10.0)
.set(self.ids.address_bg, ui_widgets);
for event in TextBox::new(&self.server_address)
.w_h(580.0/2.0, 60.0/2.0)
.mid_bottom_with_margin_on(self.ids.address_bg, 44.0/2.0)
.w_h(580.0 / 2.0, 60.0 / 2.0)
.mid_bottom_with_margin_on(self.ids.address_bg, 44.0 / 2.0)
.font_size(20)
.font_id(self.font_whitney)
.text_color(Color::Rgba(220.0, 220.0, 220.0, 0.8))
// transparent background
.color(TRANSPARENT)
.border_color(TRANSPARENT)
.set(self.ids.address_field, ui_widgets)
{
match event {
TextBoxEvent::Update(server_address) => {
self.server_address = server_address.to_string();
}
TextBoxEvent::Enter => login!(),
{
match event {
TextBoxEvent::Update(server_address) => {
self.server_address = server_address.to_string();
}
TextBoxEvent::Enter => login!(),
}
}
// Login button
if Button::image(self.imgs.login_button)
.hover_image(self.imgs.login_button_hover)
@ -225,54 +242,74 @@ impl MainMenuUi {
.w_h(258.0, 68.0)
.down_from(self.ids.address_bg, 20.0)
.align_middle_x_of(self.ids.address_bg)
.label("Login")
.label_rgba(220.0, 220.0, 220.0, 0.8)
.label_font_size(28)
.label_y(conrod_core::position::Relative::Scalar(5.0))
.set(self.ids.login_button, ui_widgets)
.was_clicked()
{
login!();
}
Image::new(self.imgs.login_text)
.w_h(83.0, 34.0)
.graphics_for(self.ids.login_button) // capture the input for the button
.middle_of(self.ids.login_button)
.set(self.ids.login_text, ui_widgets);
// Other buttons
{
login!();
}
//Singleplayer button
if Button::image(self.imgs.login_button)
.hover_image(self.imgs.login_button_hover)
.press_image(self.imgs.login_button_press)
.w_h(258.0, 68.0)
.down_from(self.ids.login_button, 20.0)
.align_middle_x_of(self.ids.address_bg)
.label("Singleplayer")
.label_rgba(220.0, 220.0, 220.0, 0.8)
.label_font_size(26)
.label_y(conrod_core::position::Relative::Scalar(5.0))
.label_x(conrod_core::position::Relative::Scalar(2.0))
.set(self.ids.singleplayer_button, ui_widgets)
.was_clicked()
{
login!();
}
// Quit
Button::image(self.imgs.button)
if Button::image(self.imgs.button)
.w_h(203.0, 53.0)
.bottom_left_with_margins_on(ui_widgets.window, 60.0, 30.0)
.hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press)
.set(self.ids.quit_button, ui_widgets);
Image::new(self.imgs.quit_text)
.w_h(52.0, 26.0)
.graphics_for(self.ids.quit_button) // capture the input for the button
.middle_of(self.ids.quit_button)
.set(self.ids.quit_text, ui_widgets);
.label("Quit")
.label_rgba(220.0, 220.0, 220.0, 0.8)
.label_font_size(20)
.label_y(conrod_core::position::Relative::Scalar(3.0))
.set(self.ids.quit_button, ui_widgets)
.was_clicked()
{
use PlayStateResult::Shutdown;
PlayStateResult::Pop;
};
// Settings
Button::image(self.imgs.button)
if Button::image(self.imgs.button)
.w_h(203.0, 53.0)
.up_from(self.ids.quit_button, 8.0)
.hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press)
.set(self.ids.settings_button, ui_widgets);
Image::new(self.imgs.settings_text)
.w_h(98.0, 28.0)
.graphics_for(self.ids.settings_button)
.middle_of(self.ids.settings_button)
.set(self.ids.settings_text, ui_widgets);
.label("Settings")
.label_rgba(220.0, 220.0, 220.0, 0.8)
.label_font_size(20)
.label_y(conrod_core::position::Relative::Scalar(3.0))
.set(self.ids.settings_button, ui_widgets)
.was_clicked()
{};
// Servers
Button::image(self.imgs.button)
if Button::image(self.imgs.button)
.w_h(203.0, 53.0)
.up_from(self.ids.settings_button, 8.0)
.hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press)
.set(self.ids.servers_button, ui_widgets);
Image::new(self.imgs.servers_text)
.w_h(93.0, 20.0)
.graphics_for(self.ids.servers_button)
.middle_of(self.ids.servers_button)
.set(self.ids.servers_text, ui_widgets);
.label("Servers")
.label_rgba(220.0, 220.0, 220.0, 0.8)
.label_font_size(20)
.label_y(conrod_core::position::Relative::Scalar(3.0))
.set(self.ids.servers_button, ui_widgets)
.was_clicked()
{};
}
pub fn handle_event(&mut self, input: Input) {

View File

@ -1,3 +1,2 @@
pub mod title;
pub mod main;
pub mod test_hud;
pub mod title;

View File

@ -1,273 +0,0 @@
// TODO: figure out where exactly this code should be located
// Library
use conrod_core::{
Positionable,
Sizeable,
Widget,
Labelable,
widget_ids,
event::Input,
image::Id as ImgId,
text::font::Id as FontId,
widget::{
Image,
Button,
Canvas,
}
};
// Crate
use crate::{
window::Window,
render::Renderer,
ui::Ui,
};
widget_ids!{
struct Ids {
bag,
bag_contents,
bag_close,
menu_top,
menu_mid,
menu_bot,
menu_canvas,
menu_buttons[],
bag_belt,
belt_buttons[],
mmap_frame,
sbar_bg
}
}
// TODO: make macro to mimic widget_ids! for images ids or find another solution to simplify addition of new images.
struct Imgs {
//Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame
// Bag
bag: ImgId,
bag_hover: ImgId,
bag_press: ImgId,
bag_open: ImgId,
bag_open_hover: ImgId,
bag_open_press: ImgId,
bag_contents: ImgId,
// Close button
close_button: ImgId,
close_button_hover: ImgId,
close_button_press: ImgId,
// Settings belt
belt_bg: ImgId,
belt_grid: ImgId,
belt_grid_hover: ImgId,
belt_grid_press: ImgId,
//belt_grid_open: ImgId,
// Menu
menu_top: ImgId,
menu_mid: ImgId,
menu_bot: ImgId,
menu_button: ImgId,
// MiniMap
mmap_frame: ImgId,
// SkillBar
sbar_bg: ImgId
}
impl Imgs {
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
let mut load = |filename| {
let image = image::open(&[env!("CARGO_MANIFEST_DIR"), "/test_assets/ui/hud/", filename].concat()).unwrap();
ui.new_image(renderer, &image).unwrap()
};
Imgs {
// Bag
bag: load("bag/icon/0_bag.png"),
bag_hover: load("bag/icon/1_bag_hover.png"),
bag_press: load("bag/icon/2_bag_press.png"),
bag_open: load("bag/icon/3_bag_open.png"),
bag_open_hover: load("bag/icon/4_bag_open_hover.png"),
bag_open_press: load("bag/icon/5_bag_open_press.png"),
bag_contents: load("bag/bg.png"),
// Close button
close_button: load("x/0_x.png"),
close_button_hover: load("x/1_x_hover.png"),
close_button_press: load("x/2_x_press.png"),
// Settings belt
belt_bg: load("belt/belt_bg.png"),
belt_grid: load("belt/belt_grid.png"),
belt_grid_hover: load("belt/belt_hover.png"),
belt_grid_press: load("belt/belt_press.png"),
//belt_grid_open: load("belt/belt_open.png"),
// Menu
menu_button: load("menu/main/menu_button.png"),
menu_top: load("menu/main/menu_top.png"),
menu_mid: load("menu/main/menu_mid.png"),
menu_bot: load("menu/main/menu_bottom.png"),
// MiniMap
mmap_frame: load("mmap/mmap_frame.png"),
// SkillBar
sbar_bg: load("skill_bar/sbar_bg.png"),
}
}
}
pub struct TestHud {
ui: Ui,
ids: Ids,
imgs: Imgs,
bag_open: bool,
menu_open: bool,
font_id: FontId,
}
impl TestHud {
pub fn new(window: &mut Window) -> Self {
let mut ui = Ui::new(window).unwrap();
// Generate ids
let mut ids = Ids::new(ui.id_generator());
ids.menu_buttons.resize(5, &mut ui.id_generator());
ids.belt_buttons.resize(6, &mut ui.id_generator());
// Load images
let imgs = Imgs::new(&mut ui, window.renderer_mut());
// Load font
let font_id = ui.new_font(conrod_core::text::font::from_file(
concat!(env!("CARGO_MANIFEST_DIR"), "/test_assets/font/Metamorphous-Regular.ttf")
).unwrap());
Self {
ui,
imgs,
ids,
bag_open: false,
menu_open: false,
font_id,
}
}
fn update_layout(&mut self) {
let ref mut ui_widgets = self.ui.set_widgets();
// Check if the bag was clicked
// (can't use .was_clicked() because we are changing the image and this is after setting the widget which causes flickering as it takes a frame to change after the mouse button is lifted)
if ui_widgets.widget_input(self.ids.bag).clicks().left().count() % 2 == 1 {
self.bag_open = !self.bag_open;
}
// Bag contents
// Note that display_contents is set before checking if the bag was clicked
// this ensures that the contents and open bag img are displayed on the same frame
if self.bag_open {
// Contents
Image::new(self.imgs.bag_contents)
.w_h(1504.0/4.0, 1760.0/4.0)
.bottom_right_with_margins(88.0, 68.0)
.set(self.ids.bag_contents, ui_widgets);
// X-button
if Button::image(self.imgs.close_button)
.w_h(144.0/4.0, 144.0/4.0)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(self.ids.bag_contents, 0.0, 12.0)
.set(self.ids.bag_close, ui_widgets)
.was_clicked() {
self.bag_open = false;
}
}
// Belt menu
Image::new(self.imgs.belt_bg)
.w_h(448.0/2.0, 56.0/2.0)
.bottom_left_with_margins_on(self.ids.bag, 5.0, -167.0)
.set(self.ids.bag_belt, ui_widgets);
// Belt buttons
for i in 0..6 {
Button::image(self.imgs.belt_grid)
.w_h(56.0/2.0, 56.0/2.0)
.bottom_left_with_margins_on(self.ids.bag_belt, 0.0, 28.0 * i as f64)
.hover_image(self.imgs.belt_grid_hover)
.press_image(self.imgs.belt_grid_press)
.set(self.ids.belt_buttons[i], ui_widgets);
}
// Minimap frame
Image::new(self.imgs.mmap_frame)
.w_h(1232.0/8.0, 976.0/8.0)
.top_right_of(ui_widgets.window)
.set(self.ids.mmap_frame, ui_widgets);
// Action bar
Image::new(self.imgs.sbar_bg)
.w_h(2240.0/8.0, 906.0/8.0)
.mid_bottom_of(ui_widgets.window)
.set(self.ids.sbar_bg, ui_widgets);
// Bag
Button::image(if self.bag_open {self.imgs.bag_open} else {self.imgs.bag})
.bottom_right_with_margin_on(ui_widgets.window, 20.0)
.hover_image(if self.bag_open {self.imgs.bag_open_hover} else {self.imgs.bag_hover})
.press_image(if self.bag_open {self.imgs.bag_open_press} else {self.imgs.bag_press})
.w_h(420.0/4.0, 480.0/4.0)
.set(self.ids.bag, ui_widgets);
// An attempt to make a resizable image based container for buttons
// Maybe this could be made into a Widget type if it is useful
if self.menu_open {
let num = self.ids.menu_buttons.len();
// Canvas to hold everything together
Canvas::new()
.w_h(106.0, 54.0 + num as f64 * 30.0)
.middle_of(ui_widgets.window)
.set(self.ids.menu_canvas, ui_widgets);
// Top of menu
Image::new(self.imgs.menu_top)
.w_h(106.0, 28.0)
.mid_top_of(self.ids.menu_canvas)
.set(self.ids.menu_top, ui_widgets);
// Bottom of Menu
// Note: conrod defaults to the last used parent
Image::new(self.imgs.menu_bot)
.w_h(106.0, 26.0)
.mid_bottom()
.set(self.ids.menu_bot, ui_widgets);
// Midsection background
Image::new(self.imgs.menu_mid)
.w_h(106.0, num as f64 * 30.0)
.mid_bottom_with_margin(26.0)
.set(self.ids.menu_mid, ui_widgets);
// Menu buttons
if num > 0 {
Button::image(self.imgs.menu_button)
.mid_top_with_margin_on(self.ids.menu_mid, 8.0)
.w_h(48.0, 20.0)
.label(&format!("Button {}", 1))
.label_rgb(1.0, 0.4, 1.0)
.label_font_size(7)
.set(self.ids.menu_buttons[0], ui_widgets);
}
for i in 1..num {
Button::image(self.imgs.menu_button)
.down(10.0)
.label(&format!("Button {}", i + 1))
.label_rgb(1.0, 0.4, 1.0)
.label_font_size(7)
.set(self.ids.menu_buttons[i], ui_widgets);
}
}
}
pub fn toggle_menu(&mut self) {
self.menu_open = !self.menu_open;
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
}
pub fn maintain(&mut self, renderer: &mut Renderer) {
self.update_layout();
self.ui.maintain(renderer);
}
pub fn render(&self, renderer: &mut Renderer) {
self.ui.render(renderer);
}
}

View File

@ -1,19 +1,14 @@
mod ui;
use std::time::Duration;
use vek::*;
use common::clock::Clock;
use crate::{
PlayState,
PlayStateResult,
GlobalState,
window::{
Event,
Window,
},
};
use super::main::MainMenuState;
use crate::{
window::{Event, Window},
GlobalState, PlayState, PlayStateResult,
};
use common::clock::Clock;
use std::time::Duration;
use ui::TitleUi;
use vek::*;
const FPS: u64 = 60;
@ -25,18 +20,21 @@ impl TitleState {
/// Create a new `TitleState`
pub fn new(window: &mut Window) -> Self {
Self {
title_ui: TitleUi::new(window)
title_ui: TitleUi::new(window),
}
}
}
// The background colour
const BG_COLOR: Rgba<f32> = Rgba { r: 0.0, g: 0.3, b: 1.0, a: 1.0 };
const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0,
g: 0.3,
b: 1.0,
a: 1.0,
};
impl PlayState for TitleState {
fn play(&mut self, global_state: &mut GlobalState) -> PlayStateResult {
// Set up an fps clock
let mut clock = Clock::new();
@ -45,16 +43,18 @@ impl PlayState for TitleState {
for event in global_state.window.fetch_events() {
match event {
Event::Close => return PlayStateResult::Shutdown,
// When space is pressed, go to the main menu
Event::Char(' ') => return PlayStateResult::Push(
Box::new(MainMenuState::new(&mut global_state.window)),
),
// When any key is pressed, go to the main menu
Event::Char(_) => {
return PlayStateResult::Push(Box::new(MainMenuState::new(
&mut global_state.window,
)));
}
// Pass events to ui
Event::UiEvent(input) => {
self.title_ui.handle_event(input);
}
// Ignore all other events
_ => {},
_ => {}
}
}
@ -68,15 +68,17 @@ impl PlayState for TitleState {
// Finish the frame
global_state.window.renderer_mut().flush();
global_state.window
global_state
.window
.swap_buffers()
.expect("Failed to swap window buffers");
// Wait for the next tick
clock.tick(Duration::from_millis(1000 / FPS));
}
}
fn name(&self) -> &'static str { "Title" }
fn name(&self) -> &'static str {
"Title"
}
}

View File

@ -1,17 +1,9 @@
use crate::{render::Renderer, ui::Ui, window::Window};
use conrod_core::{
Positionable,
Widget,
event::Input,
image::Id as ImgId,
widget::{
Image as ImageWidget,
Id as WidgId,
}
};
use crate::{
window::Window,
render::Renderer,
ui::Ui
widget::{Id as WidgId, Image as ImageWidget},
Positionable, Widget,
};
pub struct TitleUi {
@ -24,7 +16,12 @@ impl TitleUi {
pub fn new(window: &mut Window) -> Self {
let mut ui = Ui::new(window).unwrap();
let widget_id = ui.id_generator().next();
let image = image::open(concat!(env!("CARGO_MANIFEST_DIR"), "/test_assets/ui/title/test.png")).unwrap();
// TODO: use separate image for logo
let image = image::open(concat!(
env!("CARGO_MANIFEST_DIR"),
"/test_assets/ui/title/splash.png"
))
.unwrap();
let title_img_id = ui.new_image(window.renderer_mut(), &image).unwrap();
Self {
ui,

View File

@ -21,7 +21,7 @@ use crate::{
window::{Event, Key, Window},
render::Renderer,
scene::Scene,
menu::test_hud::TestHud,
hud::Hud,
};
const FPS: u64 = 60;
@ -30,8 +30,7 @@ pub struct SessionState {
scene: Scene,
client: Client,
key_state: KeyState,
// TODO: remove this
test_hud: TestHud,
hud: Hud,
}
/// Represents an active game session (i.e: one that is being played)
@ -44,7 +43,7 @@ impl SessionState {
scene: Scene::new(window.renderer_mut(), &client),
client,
key_state: KeyState::new(),
test_hud: TestHud::new(window),
hud: Hud::new(window),
})
}
}
@ -83,7 +82,7 @@ impl SessionState {
// Render the screen using the global renderer
self.scene.render_to(renderer);
// Draw the UI to the screen
self.test_hud.render(renderer);
self.hud.render(renderer);
// Finish the frame
renderer.flush();
@ -111,12 +110,16 @@ impl PlayState for SessionState {
loop {
// Handle window events
for event in global_state.window.fetch_events() {
let _handled = match event {
Event::Close => return PlayStateResult::Shutdown,
// When 'q' is pressed, exit the session
Event::Char('q') => return PlayStateResult::Pop,
// When 'm' is pressed, open/close the in-game test menu
Event::Char('m') => self.test_hud.toggle_menu(),
Event::Char('m') => self.hud.toggle_menu(),
// Close windows on esc
Event::KeyDown(Key::Escape) => self.hud.toggle_windows(),
// Toggle cursor grabbing
Event::KeyDown(Key::ToggleCursor) => {
global_state.window.grab_cursor(!global_state.window.is_cursor_grabbed());
@ -133,7 +136,7 @@ impl PlayState for SessionState {
Event::KeyUp(Key::MoveRight) => self.key_state.right = false,
// Pass events to ui
Event::UiEvent(input) => {
self.test_hud.handle_event(input);
self.hud.handle_event(input);
}
// Pass all other events to the scene
event => { self.scene.handle_input_event(event); },
@ -148,7 +151,7 @@ impl PlayState for SessionState {
// Maintain the scene
self.scene.maintain(global_state.window.renderer_mut(), &self.client);
// Maintain the UI
self.test_hud.maintain(global_state.window.renderer_mut());
self.hud.maintain(global_state.window.renderer_mut());
// Render the session
self.render(global_state.window.renderer_mut());

View File

@ -28,13 +28,13 @@ impl Window {
let events_loop = glutin::EventsLoop::new();
let win_builder = glutin::WindowBuilder::new()
.with_title("Veloren (Voxygen)")
.with_dimensions(glutin::dpi::LogicalSize::new(800.0, 500.0))
.with_maximized(false);
.with_title("Veloren")
.with_dimensions(glutin::dpi::LogicalSize::new(1366.0, 768.0))
.with_maximized(true);
let ctx_builder = glutin::ContextBuilder::new()
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
.with_vsync(true);
.with_vsync(false);
let (
window,
@ -49,7 +49,8 @@ impl Window {
).map_err(|err| Error::BackendError(Box::new(err)))?;
let mut key_map = HashMap::new();
key_map.insert(glutin::VirtualKeyCode::Escape, Key::ToggleCursor);
key_map.insert(glutin::VirtualKeyCode::Tab, Key::ToggleCursor);
key_map.insert(glutin::VirtualKeyCode::Escape, Key::Escape);
key_map.insert(glutin::VirtualKeyCode::W, Key::MoveForward);
key_map.insert(glutin::VirtualKeyCode::A, Key::MoveLeft);
key_map.insert(glutin::VirtualKeyCode::S, Key::MoveBack);
@ -84,12 +85,12 @@ impl Window {
let mut events = vec![];
self.events_loop.poll_events(|event| match {
// Hack grab of events for testing ui
if let Some(event) = conrod_winit::convert_event(event.clone(), window.window()) {
if let Some(event) = conrod_winit::convert_event(event.clone(), window.window()) {
events.push(Event::UiEvent(event));
}
}
event
} {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::CloseRequested => events.push(Event::Close),
glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => {
let (mut color_view, mut depth_view) = renderer.target_views_mut();
@ -101,6 +102,7 @@ impl Window {
events.push(Event::Resize(Vec2::new(width as u32, height as u32)));
},
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
Some(keycode) => match key_map.get(&keycode) {
Some(&key) => events.push(match input.state {
@ -157,6 +159,7 @@ pub enum Key {
MoveBack,
MoveLeft,
MoveRight,
Escape,
}
/// Represents an incoming event from the window

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/charwindow/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/charwindow/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/map/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/map/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/map/window_frame_map.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/menu/Button_dark_press.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/menu/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/menu/button_dark.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/menu/button_dark_hover.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/menu/fireplace_1.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/grid.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/hover.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/mmap_bg.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/mmap_icons.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/open.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/mmap/press.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/questlog/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/questlog/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/settings/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

BIN
voxygen/test_assets/ui/hud/settings/check.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/check_checked.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/check_checked_mo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/check_mo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/check_press.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/mo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/press.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/slider.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/settings/slider_indicator.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

BIN
voxygen/test_assets/ui/hud/skill_bar/health_bar.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/health_bar_filled.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/l.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/mana_bar.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/mana_bar_full.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/r.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/sbar_grid.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/sbar_grid_bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/xp_bar.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/xp_bar_l.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/xp_bar_l_filled.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/skill_bar/xp_bar_r.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/social/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/social/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/hud/spellbook/bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/spellbook/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/window_frame.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/window_frame_map.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/window_frame_old.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/x/0_x.png (Stored with Git LFS)

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/x/1_x_hover.png (Stored with Git LFS)

Binary file not shown.

BIN
voxygen/test_assets/ui/hud/x/2_x_press.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/main/text/White/login.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/White/quit.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/White/server_address.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/White/servers.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/White/settings.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/White/username.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

BIN
voxygen/test_assets/ui/main/text/Yellow/a01.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/login.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/quit.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/server_address.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/servers.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/settings.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/Yellow/username.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
voxygen/test_assets/ui/main/text/a01.png (Stored with Git LFS) Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More