add char selection playstate

Former-commit-id: 1d97cf90686532cb354d12f79a129a0a9c7fde98
This commit is contained in:
Imbris 2019-03-17 13:52:54 -04:00
parent 03b20fa1bd
commit d82adb7e71
8 changed files with 174 additions and 53 deletions

View File

@ -9,8 +9,8 @@ use conrod_core::{
event::Input,
image::Id as ImgId,
text::font::Id as FontId,
widget::{text_box::Event as TextBoxEvent, Button, Canvas, Image, TextBox, Text, TitleBar},
widget_ids, Borderable, Color,
widget::{Button, Image, Text, TitleBar},
widget_ids, Borderable,
Colorable, Labelable, Positionable, Sizeable, Widget,
};
@ -374,8 +374,8 @@ impl Hud {
}
fn update_layout(&mut self) -> Vec<Event> {
let ref mut ui_widgets = self.ui.set_widgets();
let mut events = Vec::new();
let ref mut ui_widgets = self.ui.set_widgets();
// Chat box
if let Some(msg) = self.chat.update_layout(ui_widgets) {

View File

@ -0,0 +1,83 @@
mod ui;
use crate::{
window::{Event, Window},
session::SessionState,
GlobalState, PlayState, PlayStateResult,
};
use common::clock::Clock;
use std::time::Duration;
use ui::CharSelectionUi;
use vek::*;
const FPS: u64 = 60;
pub struct CharSelectionState {
char_selection_ui: CharSelectionUi,
}
impl CharSelectionState {
/// Create a new `CharSelectionState`
pub fn new(window: &mut Window) -> Self {
Self {
char_selection_ui: CharSelectionUi::new(window),
}
}
}
// The background colour
const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0,
g: 0.3,
b: 1.0,
a: 1.0,
};
impl PlayState for CharSelectionState {
fn play(&mut self, global_state: &mut GlobalState) -> PlayStateResult {
// Set up an fps clock
let mut clock = Clock::new();
loop {
// Handle window events
for event in global_state.window.fetch_events() {
match event {
Event::Close => return PlayStateResult::Shutdown,
// When any key is pressed, go to the main menu
Event::Char(_) =>
return PlayStateResult::Push(
Box::new(SessionState::new(&mut global_state.window).unwrap()) // TODO: Handle this error
),
// Pass events to ui
Event::UiEvent(input) => {
self.char_selection_ui.handle_event(input);
}
// Ignore all other events
_ => {}
}
}
global_state.window.renderer_mut().clear(BG_COLOR);
// Maintain the UI
self.char_selection_ui.maintain(global_state.window.renderer_mut());
// Draw the UI to the screen
self.char_selection_ui.render(global_state.window.renderer_mut());
// Finish the frame
global_state.window.renderer_mut().flush();
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"
}
}

View File

@ -0,0 +1,51 @@
use crate::{render::Renderer, ui::Ui, window::Window};
use conrod_core::{
event::Input,
image::Id as ImgId,
widget::{Id as WidgId, Image as ImageWidget},
Positionable, Widget,
};
pub struct CharSelectionUi {
ui: Ui,
widget_id: WidgId,
splash_img_id: ImgId,
}
impl CharSelectionUi {
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/char_selection/splash.png"
))
.unwrap();
let splash_img_id = ui.new_image(window.renderer_mut(), &image).unwrap();
Self {
ui,
widget_id,
splash_img_id,
}
}
fn ui_layout(&mut self) {
let mut ui_cell = self.ui.set_widgets();
ImageWidget::new(self.splash_img_id)
.top_left()
.set(self.widget_id, &mut ui_cell);
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
}
pub fn maintain(&mut self, renderer: &mut Renderer) {
self.ui_layout();
self.ui.maintain(renderer);
}
pub fn render(&self, renderer: &mut Renderer) {
self.ui.render(renderer);
}
}

View File

@ -1,13 +1,13 @@
mod ui;
use super::char_selection::CharSelectionState;
use crate::{
session::SessionState,
window::{Event, Window},
GlobalState, PlayState, PlayStateResult,
};
use common::clock::Clock;
use std::time::Duration;
use ui::MainMenuUi;
use ui::{Event as MainMenuEvent, MainMenuUi};
use vek::*;
const FPS: u64 = 60;
@ -55,14 +55,15 @@ impl PlayState for MainMenuState {
global_state.window.renderer_mut().clear(BG_COLOR);
// Maintain the UI
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
return PlayStateResult::Push(
Box::new(SessionState::new(&mut global_state.window).unwrap()) // TODO: Handle this error
);
for event in self.main_menu_ui.maintain(global_state.window.renderer_mut()) {
match event {
MainMenuEvent::LoginAttempt{ username, server_address } =>
// For now just start a new session
return PlayStateResult::Push(
Box::new(CharSelectionState::new(&mut global_state.window))
),
MainMenuEvent::Quit => return PlayStateResult::Shutdown,
}
}
// Draw the UI to the screen

View File

@ -2,16 +2,14 @@ use crate::{
render::Renderer,
ui::{ScaleMode, Ui},
window::Window,
Error, GlobalState, PlayState, PlayStateResult,
};
use conrod_core::{
color::TRANSPARENT,
event::Input,
image::Id as ImgId,
text::font::Id as FontId,
widget::{text_box::Event as TextBoxEvent, Button, Canvas, Image, TextBox},
widget::{text_box::Event as TextBoxEvent, Button, Image, TextBox},
widget_ids, Borderable, Color,
Color::Rgba,
Colorable, Labelable, Positionable, Sizeable, Widget,
};
@ -34,32 +32,21 @@ widget_ids! {
singleplayer_text,
// Buttons
servers_button,
servers_text,
settings_button,
settings_text,
quit_button,
quit_text,
}
}
struct Imgs {
bg: ImgId,
v_logo: ImgId,
alpha_version: ImgId,
address_text: ImgId,
username_text: ImgId,
input_bg: ImgId,
login_text: ImgId,
login_button: ImgId,
login_button_hover: ImgId,
login_button_press: ImgId,
singleplayer_text: ImgId,
servers_text: ImgId,
settings_text: ImgId,
quit_text: ImgId,
button: ImgId,
button_hover: ImgId,
button_press: ImgId,
@ -81,24 +68,16 @@ impl Imgs {
Imgs {
bg: load("bg.png"),
v_logo: load("v_logo.png"),
alpha_version: load("text/a01.png"),
// Input fields
address_text: load("text/server_address.png"),
username_text: load("text/username.png"),
input_bg: load("input_bg.png"),
// 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"),
// Servers, settings, and quit buttons
servers_text: load("text/servers.png"),
settings_text: load("text/settings.png"),
quit_text: load("text/quit.png"),
button: load("buttons/button.png"),
button_hover: load("buttons/button_hover.png"),
button_press: load("buttons/button_press.png"),
@ -106,6 +85,14 @@ impl Imgs {
}
}
pub enum Event {
LoginAttempt {
username: String,
server_address: String,
},
Quit,
}
pub struct MainMenuUi {
ui: Ui,
ids: Ids,
@ -114,7 +101,6 @@ pub struct MainMenuUi {
font_whitney: FontId,
username: String,
server_address: String,
attempt_login: bool,
}
impl MainMenuUi {
@ -149,21 +135,11 @@ impl MainMenuUi {
font_whitney,
username: "Username".to_string(),
server_address: "Server Address".to_string(),
attempt_login: false,
}
}
// TODO: probably a better way to do this
pub fn login_attempt(&mut self) -> Option<(String, String)> {
if self.attempt_login {
self.attempt_login = false;
Some((self.username.clone(), self.server_address.clone()))
} else {
None
}
}
fn update_layout(&mut self) {
fn update_layout(&mut self) -> Vec<Event> {
let mut events = Vec::new();
let ref mut ui_widgets = self.ui.set_widgets();
// Background image, Veloren logo, Alpha-Version Label
Image::new(self.imgs.bg)
@ -183,7 +159,10 @@ impl MainMenuUi {
// Used when the login button is pressed, or enter is pressed within input field
macro_rules! login {
() => {
self.attempt_login = true;
events.push(Event::LoginAttempt {
username: self.username.clone(),
server_address: self.server_address.clone(),
});
};
}
// Username
@ -281,8 +260,7 @@ impl MainMenuUi {
.set(self.ids.quit_button, ui_widgets)
.was_clicked()
{
use PlayStateResult::Shutdown;
PlayStateResult::Pop;
events.push(Event::Quit);
};
// Settings
if Button::image(self.imgs.button)
@ -310,15 +288,18 @@ impl MainMenuUi {
.set(self.ids.servers_button, ui_widgets)
.was_clicked()
{};
events
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
}
pub fn maintain(&mut self, renderer: &mut Renderer) {
self.update_layout();
pub fn maintain(&mut self, renderer: &mut Renderer) -> Vec<Event> {
let events = self.update_layout();
self.ui.maintain(renderer);
events
}
pub fn render(&self, renderer: &mut Renderer) {

View File

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

View File

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

BIN
voxygen/test_assets/ui/char_selection/splash.png (Stored with Git LFS) Normal file

Binary file not shown.