Separate settings and small windows and convert chat

Former-commit-id: 847b0b8cf64b9d2de10b241d37bb7e21c126d314
This commit is contained in:
timokoesters 2019-05-03 18:56:18 +02:00 committed by Imbris
parent f695973bb2
commit 08aa8875fd
7 changed files with 792 additions and 800 deletions

View File

@ -34,7 +34,6 @@ widget_ids! {
#[derive(WidgetCommon)]
pub struct CharacterWindow<'a> {
xp_percentage: f64,
imgs: &'a Imgs,
fonts: &'a Fonts,
@ -46,7 +45,6 @@ pub struct CharacterWindow<'a> {
impl<'a> CharacterWindow<'a> {
pub fn new(imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
Self {
xp_percentage: 0.4,
imgs,
fonts,
common: widget::CommonBuilder::default(),
@ -81,6 +79,9 @@ impl<'a> Widget for CharacterWindow<'a> {
..
} = args;
// TODO: Read from parameter / character struct
let xp_percentage = 0.4;
// Frame
Image::new(self.imgs.window_frame)
.middle_of(id)
@ -153,7 +154,7 @@ impl<'a> Widget for CharacterWindow<'a> {
.set(state.charwindow_exp_rectangle, ui);
// Exp-Bar Progress
Rectangle::fill_with([170.0 * (self.xp_percentage), 6.0], XP_COLOR) // 0.8 = Experience percentage
Rectangle::fill_with([170.0 * (xp_percentage), 6.0], XP_COLOR) // 0.8 = Experience percentage
.mid_left_with_margin_on(state.charwindow_tab1_expbar, 1.0)
.set(state.charwindow_exp_progress_rectangle, ui);

View File

@ -1,13 +1,15 @@
use crate::ui::Ui;
use super::img_ids::Imgs;
use super::font_ids::Fonts;
use conrod_core::{
color,
builder_methods, color,
input::Key,
text::font,
widget::{self, Button, Id, List, Rectangle, Text, TextEdit},
position::Dimension,
text::font::Id as FontId,
widget::{Button, Id, List, Rectangle, Text, TextEdit},
widget_ids, Colorable, Positionable, Sizeable, UiCell, Widget,
UiCell, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use super::{
img_ids::Imgs,
font_ids::Fonts,
TEXT_COLOR,
};
use std::collections::VecDeque;
@ -20,49 +22,35 @@ widget_ids! {
chat_arrow,
}
}
// Chat Behaviour:
// Input Window is only shown when the player presses Enter (graphical overlay to make it look better?)
// Instead of a Scrollbar it could have 3 Arrows at it's left side
// First two: Scroll the chat up and down
// Last one: Gets back to the bottom of the chat
// Consider making this a custom Widget
pub struct Chat {
ids: Ids,
messages: VecDeque<String>,
input: String,
new_messages: bool,
#[derive(WidgetCommon)]
pub struct Chat<'a> {
new_messages: &'a mut VecDeque<String>,
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
common: widget::CommonBuilder,
style: (),
}
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,
impl<'a> Chat<'a> {
pub fn new(new_messages: &'a mut VecDeque<String>, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
Self {
new_messages,
imgs,
fonts,
common: widget::CommonBuilder::default(),
style: (),
}
}
pub fn input_box_id(&self) -> Id {
self.ids.input
}
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(&self, ui_widgets: &mut UiCell) {
// If previously scrolled to the bottom stay there
if self.scrolled_to_bottom(ui_widgets) {
self.scroll_to_bottom(ui_widgets);
}
}
fn scrolled_to_bottom(&self, ui_widgets: &UiCell) -> bool {
fn scrolled_to_bottom(state: &State, ui: &UiCell) -> bool {
// could be more efficient to cache result and update it when a scroll event has occurred instead of every frame
if let Some(scroll) = ui_widgets
if let Some(scroll) = ui
.widget_graph()
.widget(self.ids.message_box)
.widget(state.ids.message_box)
.and_then(|widget| widget.maybe_y_scroll_state)
{
scroll.offset >= scroll.offset_bounds.start
@ -70,50 +58,77 @@ impl Chat {
false
}
}
fn scroll_to_bottom(&self, ui_widgets: &mut UiCell) {
ui_widgets.scroll_widget(self.ids.message_box, [0.0, std::f64::MAX]);
}
pub struct State {
messages: VecDeque<String>,
input: String,
ids: Ids,
}
pub enum Event {
SendMessage(String),
}
impl<'a> Widget for Chat<'a> {
type State = State;
type Style = ();
type Event = Option<Event>;
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
messages: VecDeque::new(),
input: "".to_owned(),
ids: Ids::new(id_gen),
}
}
pub(super) fn update_layout(
&mut self,
ui_widgets: &mut UiCell,
imgs: &Imgs,
fonts: &Fonts,
) -> Option<String> {
fn style(&self) -> Self::Style {
()
}
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
let widget::UpdateArgs {
id,
state,
ui,
style,
..
} = args;
// Maintain scrolling
if self.new_messages {
self.scroll_new_messages(ui_widgets);
self.new_messages = false;
if !self.new_messages.is_empty() {
state.update(|s| s.messages.extend(self.new_messages.drain(..)));
ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]);
}
// Only show if it has the keyboard captured
// Chat input with rectangle as background
let keyboard_captured = ui_widgets
.global_input()
.current
.widget_capturing_keyboard
.map_or(false, |id| id == self.ids.input);
let keyboard_captured = ui.global_input().current.widget_capturing_keyboard == Some(id);
if keyboard_captured {
let text_edit = TextEdit::new(&self.input)
let text_edit = TextEdit::new(&state.input)
.w(460.0)
.restrict_to_height(false)
.line_spacing(2.0)
.font_size(15)
.font_id(fonts.opensans);
let y = match text_edit.get_y_dimension(ui_widgets) {
.font_id(self.fonts.opensans);
let y = match text_edit.get_y_dimension(ui) {
Dimension::Absolute(y) => y + 6.0,
_ => 0.0,
};
Rectangle::fill([470.0, y])
.rgba(0.0, 0.0, 0.0, 0.8)
.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
.bottom_left_with_margins_on(ui.window, 10.0, 10.0)
.w(470.0)
.set(self.ids.input_bg, ui_widgets);
.set(state.ids.input_bg, ui);
if let Some(str) = text_edit
.top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0)
.set(self.ids.input, ui_widgets)
.top_left_with_margins_on(state.ids.input_bg, 1.0, 1.0)
.set(state.ids.input, ui)
{
self.input = str.to_string();
self.input.retain(|c| c != '\n');
let mut input = str.to_owned();
input.retain(|c| c != '\n');
state.update(|s| s.input = input);
}
}
@ -127,23 +142,23 @@ impl Chat {
r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
}
})
.set(self.ids.message_box_bg, ui_widgets);
let (mut items, _) = List::flow_down(self.messages.len() + 1)
.top_left_of(self.ids.message_box_bg)
.set(state.ids.message_box_bg, ui);
let (mut items, _) = List::flow_down(state.messages.len() + 1)
.top_left_of(state.ids.message_box_bg)
.w_h(470.0, 174.0)
.scroll_kids_vertically()
.set(self.ids.message_box, ui_widgets);
while let Some(item) = items.next(ui_widgets) {
.set(state.ids.message_box, ui);
while let Some(item) = items.next(ui) {
// This would be easier if conrod used the v-metrics from rusttype
let widget = if item.i < self.messages.len() {
let text = Text::new(&self.messages[item.i])
let widget = if item.i < state.messages.len() {
let text = Text::new(&state.messages[item.i])
.font_size(15)
.font_id(fonts.opensans)
.font_id(self.fonts.opensans)
.w(470.0)
.rgba(1.0, 1.0, 1.0, 1.0)
.line_spacing(2.0);
// Add space between messages
let y = match text.get_y_dimension(ui_widgets) {
let y = match text.get_y_dimension(ui) {
Dimension::Absolute(y) => y + 2.0,
_ => 0.0,
};
@ -151,40 +166,41 @@ impl Chat {
} else {
// Spacer at bottom of the last message so that it is not cut off
// Needs to be larger than the space above
Text::new("").font_size(6).font_id(fonts.opensans).w(470.0)
Text::new("").font_size(6).font_id(self.fonts.opensans).w(470.0)
};
item.set(widget, ui_widgets);
item.set(widget, ui);
}
// Chat Arrow
if !self.scrolled_to_bottom(ui_widgets) {
if Button::image(imgs.chat_arrow)
// Check if already at bottom
if !Self::scrolled_to_bottom(state, ui) {
if Button::image(self.imgs.chat_arrow)
.w_h(20.0, 20.0)
.hover_image(imgs.chat_arrow_mo)
.press_image(imgs.chat_arrow_press)
.bottom_right_with_margins_on(self.ids.message_box_bg, 0.0, -22.0)
.set(self.ids.chat_arrow, ui_widgets)
.hover_image(self.imgs.chat_arrow_mo)
.press_image(self.imgs.chat_arrow_press)
.bottom_right_with_margins_on(state.ids.message_box_bg, 0.0, -22.0)
.set(state.ids.chat_arrow, ui)
.was_clicked()
{
self.scroll_to_bottom(ui_widgets);
ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]);
}
}
// If enter is pressed and the input box is not empty send the current message
if ui_widgets
.widget_input(self.ids.input)
if ui
.widget_input(state.ids.input)
.presses()
.key()
.any(|key_press| match key_press.key {
Key::Return if !self.input.is_empty() => true,
Key::Return if !state.input.is_empty() => true,
_ => false,
})
{
let new_message = self.input.clone();
self.input.clear();
Some(new_message)
} else {
None
let msg = state.input.clone();
state.update(|s| s.input.clear());
return Some(Event::SendMessage(msg))
}
None
}
}

View File

@ -6,37 +6,43 @@ use conrod_core::{
};
use super::{
imgs::Imgs,
Style, XP_COLOR,
img_ids::Imgs,
font_ids::Fonts,
TEXT_COLOR,
};
widget_ids! {
struct Ids {
esc_bg,
fireplace,
menu_button_1,
menu_button_2,
menu_button_3,
menu_button_4,
menu_button_5,
}
}
#[derive(WidgetCommon)]
pub struct EscMenu<'a> {
xp_percentage: f64,
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
common: widget::CommonBuilder,
style: Style,
style: (),
}
impl<'a> CharacterWindow<'a> {
pub fn new(imgs: &'a Imgs) -> Self {
impl<'a> EscMenu<'a> {
pub fn new(imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
Self {
xp_percentage: 0.4,
imgs,
fonts,
common: widget::CommonBuilder::default(),
style: Style::default(),
style: (),
}
}
builder_methods! {
pub text_color { style.text_color = Some(Color) }
}
}
pub struct State {
@ -44,12 +50,15 @@ pub struct State {
}
pub enum Event {
OpenSettings,
Logout,
Quit,
Close,
}
impl<'a> Widget for CharacterWindow<'a> {
impl<'a> Widget for EscMenu<'a> {
type State = State;
type Style = Style;
type Style = ();
type Event = Option<Event>;
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
@ -59,7 +68,7 @@ impl<'a> Widget for CharacterWindow<'a> {
}
fn style(&self) -> Self::Style {
self.style.clone()
()
}
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
@ -71,94 +80,92 @@ impl<'a> Widget for CharacterWindow<'a> {
..
} = args;
let font_id = style.font_id(&ui.theme).or(ui.fonts.ids().next());
let text_color = style.text_color(&ui.theme);
Image::new(self.imgs.esc_bg)
.w_h(228.0, 450.0)
.middle_of(ui.window)
.set(state.ids.esc_bg, ui);
if self.menu_open {
Image::new(self.imgs.esc_bg)
.w_h(228.0, 450.0)
.middle_of(ui_widgets.window)
.set(self.ids.esc_bg, ui_widgets);
Image::new(self.imgs.fireplace)
.w_h(180.0, 60.0)
.mid_top_with_margin_on(state.ids.esc_bg, 50.0)
.set(state.ids.fireplace, ui);
Image::new(self.imgs.fireplace)
.w_h(180.0, 60.0)
.mid_top_with_margin_on(self.ids.esc_bg, 50.0)
.set(self.ids.fireplace, ui_widgets);
// Settings
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(state.ids.esc_bg, 115.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Settings")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(state.ids.menu_button_1, ui)
.was_clicked()
{
return Some(Event::OpenSettings);
};
// Controls
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(state.ids.esc_bg, 175.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Controls")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(state.ids.menu_button_2, ui)
.was_clicked()
{
//self.menu_open = false;
};
// Servers
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(state.ids.esc_bg, 235.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Servers")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(state.ids.menu_button_3, ui)
.was_clicked()
{
//self.menu_open = false;
};
// Logout
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(state.ids.esc_bg, 295.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Logout")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(state.ids.menu_button_4, ui)
.was_clicked()
{
return Some(Event::Logout);
};
// Quit
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(state.ids.esc_bg, 355.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Quit")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(state.ids.menu_button_5, ui)
.was_clicked()
{
return Some(Event::Quit);
};
// Settings
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(self.ids.esc_bg, 115.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Settings")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(self.ids.menu_button_1, ui_widgets)
.was_clicked()
{
self.menu_open = false;
self.open_windows = Windows::Settings;
};
// Controls
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(self.ids.esc_bg, 175.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Controls")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(self.ids.menu_button_2, ui_widgets)
.was_clicked()
{
//self.menu_open = false;
};
// Servers
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(self.ids.esc_bg, 235.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Servers")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(self.ids.menu_button_3, ui_widgets)
.was_clicked()
{
//self.menu_open = false;
};
// Logout
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(self.ids.esc_bg, 295.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Logout")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(self.ids.menu_button_4, ui_widgets)
.was_clicked()
{
events.push(Event::Logout);
};
// Quit
if Button::image(self.imgs.button_dark)
.mid_top_with_margin_on(self.ids.esc_bg, 355.0)
.w_h(170.0, 50.0)
.hover_image(self.imgs.button_dark_hover)
.press_image(self.imgs.button_dark_press)
.label("Quit")
.label_y(conrod_core::position::Relative::Scalar(2.0))
.label_color(TEXT_COLOR)
.label_font_size(17)
.set(self.ids.menu_button_5, ui_widgets)
.was_clicked()
{
events.push(Event::Quit);
};
}
None
}
}

View File

@ -4,6 +4,7 @@ use conrod_core::{
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use super::{
img_ids::Imgs,
font_ids::Fonts,

View File

@ -1,11 +1,18 @@
mod chat;
mod character_window;
mod map;
mod esc_menu;
mod small_window;
mod settings_window;
mod img_ids;
mod font_ids;
use chat::Chat;
use character_window::CharacterWindow;
use map::Map;
use esc_menu::EscMenu;
use small_window::{SmallWindow, SmallWindowType};
use settings_window::SettingsWindow;
use img_ids::Imgs;
use font_ids::Fonts;
@ -23,6 +30,7 @@ use conrod_core::{
WidgetStyle, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
};
use common::assets;
use std::collections::VecDeque;
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);
@ -115,19 +123,6 @@ widget_ids! {
window_frame_4,
window_frame_5,
// 0 Settings-Window
settings_bg,
settings_content,
settings_icon,
settings_button_mo,
settings_close,
settings_title,
settings_r,
settings_l,
settings_scrollbar,
controls_text,
controls_controls,
// Contents
button_help,
button_help2,
@ -161,19 +156,15 @@ widget_ids! {
questlog_title,
// External
chat,
map,
character_window,
esc_menu,
small_window,
settings_window,
}
}
enum SettingsTab {
Interface,
Video,
Sound,
Gameplay,
Controls,
}
pub enum Event {
SendMessage(String),
Logout,
@ -185,27 +176,21 @@ pub enum Event {
// map not here because it currently is displayed over the top of other open windows
enum Windows {
Settings, // display settings window
CharacterAnd(Option<Small>), // show character window + optionally another
Small(Small),
CharacterAnd(Option<SmallWindowType>), // show character window + optionally another
Small(SmallWindowType),
None,
}
#[derive(Clone, Copy)]
enum Small {
Spellbook,
Social,
Questlog,
}
pub struct Hud {
ui: Ui,
ids: Ids,
imgs: Imgs,
fonts: Fonts,
chat: chat::Chat,
new_messages: VecDeque<String>,
show_help: bool,
show_debug: bool,
bag_open: bool,
menu_open: bool,
esc_menu_open: bool,
open_windows: Windows,
map_open: bool,
mmap_open: bool,
@ -215,8 +200,6 @@ pub struct Hud {
hp_percentage: f64,
mana_percentage: f64,
inventorytest_button: bool,
settings_tab: SettingsTab,
settings: Settings,
}
impl Hud {
@ -229,22 +212,18 @@ impl Hud {
// Load images
let imgs = Imgs::load(&mut ui).expect("Failed to load images");
// Load fonts
dbg!("Loading fonts...");
let fonts = Fonts::load(&mut ui).expect("Failed to load fonts");
// Chat box
let chat = chat::Chat::new(&mut ui);
Self {
ui,
imgs,
fonts,
ids,
chat,
settings_tab: SettingsTab::Interface,
show_help: false,
show_debug: true,
new_messages: VecDeque::new(),
show_help: true,
show_debug: false,
bag_open: false,
menu_open: false,
esc_menu_open: false,
map_open: false,
mmap_open: false,
show_ui: true,
@ -259,11 +238,11 @@ impl Hud {
}
fn update_layout(&mut self, tps: f64) -> Vec<Event> {
// Don't show anything if the UI is toggled off
let mut events = Vec::new();
let ref mut ui_widgets = self.ui.set_widgets();
let version = env!("CARGO_PKG_VERSION");
// Don't show anything if the ui is toggled off
if !self.show_ui {
return events;
}
@ -301,13 +280,12 @@ impl Hud {
};
}
// Chat box
if let Some(msg) = self
.chat
.update_layout(ui_widgets, &self.imgs, &self.fonts)
{
events.push(Event::SendMessage(msg));
}
// Alpha Version
Text::new(version)
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
.font_size(14)
.color(TEXT_COLOR)
.set(self.ids.v_logo, ui_widgets);
// Help Text
if self.show_help {
@ -384,7 +362,6 @@ impl Hud {
.set(self.ids.mmap_location, ui_widgets);
// Buttons at Bag
// 0 Settings
if Button::image(self.imgs.settings)
.w_h(29.0, 25.0)
@ -468,11 +445,11 @@ impl Hud {
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(Small::Social) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Social),
Windows::Small(SmallWindowType::Social) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Social),
Windows::CharacterAnd(small) => match small {
Some(Small::Social) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Social)),
Some(SmallWindowType::Social) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Social)),
},
Windows::Settings => Windows::Settings,
};
@ -494,11 +471,11 @@ impl Hud {
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(Small::Spellbook) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Spellbook),
Windows::Small(SmallWindowType::Spellbook) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Spellbook),
Windows::CharacterAnd(small) => match small {
Some(Small::Spellbook) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Spellbook)),
Some(SmallWindowType::Spellbook) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Spellbook)),
},
Windows::Settings => Windows::Settings,
};
@ -546,11 +523,11 @@ impl Hud {
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(Small::Questlog) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Questlog),
Windows::Small(SmallWindowType::Questlog) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Questlog),
Windows::CharacterAnd(small) => match small {
Some(Small::Questlog) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Questlog)),
Some(SmallWindowType::Questlog) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Questlog)),
},
Windows::Settings => Windows::Settings,
};
@ -558,7 +535,6 @@ impl Hud {
}
// Skillbar Module
// Experience-Bar
Image::new(self.imgs.xp_bar)
.w_h(2688.0 / 6.0, 116.0 / 6.0)
@ -727,533 +703,56 @@ impl Hud {
.set(self.ids.bag_text, ui_widgets);
}
// Chat box
match Chat::new(&mut self.new_messages, &self.imgs, &self.fonts)
.top_left_with_margins_on(ui_widgets.window, 200.0, 215.0)
.w_h(103.0 * 4.0, 122.0 * 4.0) // TODO: replace this with default_width() / height() overrides
.set(self.ids.chat, ui_widgets)
{
Some(chat::Event::SendMessage(message)) => {
events.push(Event::SendMessage(message));
}
None => {}
}
self.new_messages = VecDeque::new();
//Windows
//Char Window will always appear at the left side. Other Windows either appear at the left side,
//or when the Char Window is opened they will appear right from it.
// 0 Settings
// Settings
if let Windows::Settings = self.open_windows {
// Frame Alignment
Rectangle::fill_with([824.0, 488.0], color::TRANSPARENT)
.middle_of(ui_widgets.window)
.set(self.ids.settings_bg, ui_widgets);
// Frame
Image::new(self.imgs.settings_frame_l)
.top_left_with_margins_on(self.ids.settings_bg, 0.0, 0.0)
.w_h(412.0, 488.0)
.set(self.ids.settings_l, ui_widgets);
Image::new(self.imgs.settings_frame_r)
.right_from(self.ids.settings_l, 0.0)
.parent(self.ids.settings_bg)
.w_h(412.0, 488.0)
.set(self.ids.settings_r, ui_widgets);
// Content Alignment
Rectangle::fill_with([198.0 * 4.0, 97.0 * 4.0], color::TRANSPARENT)
.top_right_with_margins_on(self.ids.settings_r, 21.0 * 4.0, 4.0 * 4.0)
.scroll_kids()
.scroll_kids_vertically()
.set(self.ids.settings_content, ui_widgets);
Scrollbar::y_axis(self.ids.settings_content)
.thickness(5.0)
.rgba(0.33, 0.33, 0.33, 1.0)
.set(self.ids.settings_scrollbar, ui_widgets);
// 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(self.ids.settings_r, 0.0, 0.0)
.set(self.ids.settings_close, ui_widgets)
.was_clicked()
match SettingsWindow::new(&self.imgs, &self.fonts)
.top_left_with_margins_on(ui_widgets.window, 200.0, 215.0)
.w_h(103.0 * 4.0, 122.0 * 4.0) // TODO: replace this with default_width() / height() overrides
.set(self.ids.settings_window, ui_widgets)
{
self.open_windows = Windows::None;
self.settings_tab = SettingsTab::Interface;
}
// Title
Text::new("Settings")
.mid_top_with_margin_on(self.ids.settings_bg, 5.0)
.font_size(14)
.color(TEXT_COLOR)
.set(self.ids.settings_title, ui_widgets);
// Icon
//Image::new(self.imgs.settings_icon)
//.w_h(224.0 / 3.0, 224.0 / 3.0)
//.top_left_with_margins_on(self.ids.settings_bg, -10.0, -10.0)
//.set(self.ids.settings_icon, ui_widgets);
// TODO: Find out if we can remove this
// 1 Interface////////////////////////////
if Button::image(if let SettingsTab::Interface = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.blank
})
.w_h(31.0 * 4.0, 12.0 * 4.0)
.hover_image(if let SettingsTab::Interface = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_hover
})
.press_image(if let SettingsTab::Interface = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_press
})
.top_left_with_margins_on(self.ids.settings_l, 8.0 * 4.0, 2.0 * 4.0)
.label("Interface")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(self.ids.interface, ui_widgets)
.was_clicked()
{
self.settings_tab = SettingsTab::Interface;
}
// Toggle Help
if let SettingsTab::Interface = self.settings_tab {
self.show_help =
ToggleButton::new(self.show_help, self.imgs.check, self.imgs.check_checked)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.top_left_with_margins_on(self.ids.settings_content, 5.0, 5.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(self.ids.button_help, ui_widgets);
Text::new("Show Help")
.right_from(self.ids.button_help, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(self.ids.button_help)
.color(TEXT_COLOR)
.set(self.ids.show_help_label, ui_widgets);
self.inventorytest_button = ToggleButton::new(
self.inventorytest_button,
self.imgs.check,
self.imgs.check_checked,
)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.down_from(self.ids.button_help, 7.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(self.ids.inventorytest_button, ui_widgets);
Text::new("Show Inventory Test Button")
.right_from(self.ids.inventorytest_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(self.ids.inventorytest_button)
.color(TEXT_COLOR)
.set(self.ids.inventorytest_button_label, ui_widgets);
self.show_debug =
ToggleButton::new(self.show_debug, self.imgs.check, self.imgs.check_checked)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.down_from(self.ids.inventorytest_button, 7.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(self.ids.debug_button, ui_widgets);
Text::new("Show Debug Window")
.right_from(self.ids.debug_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(self.ids.debug_button)
.color(TEXT_COLOR)
.set(self.ids.debug_button_label, ui_widgets);
}
// 2 Gameplay////////////////
if Button::image(if let SettingsTab::Gameplay = self.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
Some(settings_window::Event::Close) => {
self.open_windows = Windows::None;
}
)
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.down_from(self.ids.interface, 1.0)
.label("Gameplay")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(self.ids.gameplay, ui_widgets)
.was_clicked()
{
self.settings_tab = SettingsTab::Gameplay;
}
// 3 Controls/////////////////////
if Button::image(if let SettingsTab::Controls = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.blank
})
.w_h(31.0 * 4.0, 12.0 * 4.0)
.hover_image(if let SettingsTab::Controls = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_hover
})
.press_image(if let SettingsTab::Controls = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_press
})
.right_from(self.ids.gameplay, 0.0)
.label("Controls")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(self.ids.controls, ui_widgets)
.was_clicked()
{
self.settings_tab = SettingsTab::Controls;
}
if let SettingsTab::Controls = self.settings_tab {
Text::new(
"Free Cursor\n\
Toggle Help Window\n\
Toggle Interface\n\
Toggle FPS and Debug Info\n\
\n\
\n\
Move Forward\n\
Move Left\n\
Move Right\n\
Move Backwards\n\
\n\
Jump\n\
\n\
Dodge\n\
\n\
Auto Walk\n\
\n\
Sheathe/Draw Weapons\n\
\n\
Put on/Remove Helmet\n\
\n\
\n\
Basic Attack\n\
Secondary Attack/Block/Aim\n\
\n\
\n\
Skillbar Slot 1\n\
Skillbar Slot 2\n\
Skillbar Slot 3\n\
Skillbar Slot 4\n\
Skillbar Slot 5\n\
Skillbar Slot 6\n\
Skillbar Slot 7\n\
Skillbar Slot 8\n\
Skillbar Slot 9\n\
Skillbar Slot 10\n\
\n\
\n\
Pause Menu\n\
Settings\n\
Social\n\
Map\n\
Spellbook\n\
Character\n\
Questlog\n\
Bag\n\
\n\
\n\
\n\
Send Chat Message\n\
Scroll Chat\n\
\n\
\n\
Chat commands: \n\
\n\
/alias [Name] - Change your Chat Name \n\
/tp [Name] - Teleports you to another player
",
)
.color(TEXT_COLOR)
.top_left_with_margins_on(self.ids.settings_content, 5.0, 5.0)
.font_id(self.font_opensans)
.font_size(18)
.set(self.ids.controls_text, ui_widgets);
// TODO: Replace with buttons that show the actual keybind and allow the user to change it.
Text::new(
"TAB\n\
F1\n\
F2\n\
F3\n\
\n\
\n\
W\n\
A\n\
S\n\
D\n\
\n\
SPACE\n\
\n\
??\n\
\n\
??\n\
\n\
??\n\
\n\
??\n\
\n\
\n\
L-Click\n\
R-Click\n\
\n\
\n\
1\n\
2\n\
3\n\
4\n\
5\n\
6\n\
7\n\
8\n\
9\n\
0\n\
\n\
\n\
ESC\n\
N\n\
O\n\
M\n\
P\n\
C\n\
L\n\
B\n\
\n\
\n\
\n\
ENTER\n\
Mousewheel\n\
\n\
\n\
\n\
\n\
\n\
\n\
",
)
.color(TEXT_COLOR)
.right_from(self.ids.controls_text, 0.0)
.font_id(self.font_opensans)
.font_size(18)
.set(self.ids.controls_controls, ui_widgets);
}
// 4 Video////////////////////////////////
if Button::image(if let SettingsTab::Video = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.blank
})
.w_h(31.0 * 4.0, 12.0 * 4.0)
.hover_image(if let SettingsTab::Video = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_hover
})
.press_image(if let SettingsTab::Video = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_press
})
.right_from(self.ids.controls, 0.0)
.label("Video")
.parent(self.ids.settings_r)
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(self.ids.video, ui_widgets)
.was_clicked()
{
self.settings_tab = SettingsTab::Video;
}
// 5 Sound///////////////////////////////
if Button::image(if let SettingsTab::Sound = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.blank
})
.w_h(31.0 * 4.0, 12.0 * 4.0)
.hover_image(if let SettingsTab::Sound = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_hover
})
.press_image(if let SettingsTab::Sound = self.settings_tab {
self.imgs.settings_button_pressed
} else {
self.imgs.settings_button_press
})
.right_from(self.ids.video, 0.0)
.parent(self.ids.settings_r)
.label("Sound")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(self.ids.sound, ui_widgets)
.was_clicked()
{
self.settings_tab = SettingsTab::Sound;
None => {}
}
}
// Small Window
if let Some((small, char_window_open)) = match self.open_windows {
Windows::Small(small) => Some((small, false)),
Windows::CharacterAnd(Some(small)) => Some((small, true)),
_ => None,
} {
// TODO: there is common code in each match arm, might be able to combine this
match small {
Small::Social => {
//Frame
if char_window_open {
Image::new(self.imgs.window_frame)
.right_from(self.ids.charwindow_frame, 20.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.social_frame, ui_widgets);
} else {
Image::new(self.imgs.window_frame)
.top_left_with_margins_on(ui_widgets.window, 200.0, 10.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.social_frame, ui_widgets);
}
// Icon
Image::new(self.imgs.social_icon)
.w_h(40.0, 40.0)
.top_left_with_margins_on(self.ids.social_frame, 4.0, 4.0)
.set(self.ids.social_icon, ui_widgets);
// Content alignment
Rectangle::fill_with([362.0, 418.0], color::TRANSPARENT)
.bottom_right_with_margins_on(self.ids.social_frame, 17.0, 17.0)
.scroll_kids()
.scroll_kids_vertically()
.set(self.ids.social_bg, ui_widgets);
// 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(self.ids.social_frame, 12.0, 0.0)
.set(self.ids.social_close, ui_widgets)
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(_) => Windows::None,
Windows::CharacterAnd(_) => Windows::CharacterAnd(None),
_ => Windows::Settings,
}
}
// Title
Text::new("Social")
.mid_top_with_margin_on(self.ids.social_frame, 17.0)
.font_id(self.fonts.metamorph)
.font_size(14)
.color(TEXT_COLOR)
.set(self.ids.social_title, ui_widgets);
}
Small::Spellbook => {
// Frame
if char_window_open {
Image::new(self.imgs.window_frame)
.right_from(self.ids.charwindow_frame, 20.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.spellbook_frame, ui_widgets);
} else {
Image::new(self.imgs.window_frame)
.top_left_with_margins_on(ui_widgets.window, 200.0, 10.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.spellbook_frame, ui_widgets);
}
// Icon
Image::new(self.imgs.spellbook_icon)
.w_h(40.0, 40.0)
.top_left_with_margins_on(self.ids.spellbook_frame, 4.0, 4.0)
.set(self.ids.spellbook_icon, ui_widgets);
// Content alignment
Rectangle::fill_with([362.0, 418.0], color::TRANSPARENT)
.bottom_right_with_margins_on(self.ids.spellbook_frame, 17.0, 17.0)
.scroll_kids()
.scroll_kids_vertically()
.set(self.ids.spellbook_bg, ui_widgets);
// X-Button
if Button::image(self.imgs.close_button)
.w_h(14.0, 14.0)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(self.ids.spellbook_frame, 12.0, 0.0)
.set(self.ids.spellbook_close, ui_widgets)
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(_) => Windows::None,
Windows::CharacterAnd(_) => Windows::CharacterAnd(None),
_ => Windows::Settings,
}
}
// Title
Text::new("Spellbook")
.mid_top_with_margin_on(self.ids.spellbook_frame, 17.0)
.font_size(14)
.color(TEXT_COLOR)
.set(self.ids.spellbook_title, ui_widgets);
}
Small::Questlog => {
// Frame
if char_window_open {
Image::new(self.imgs.window_frame)
.right_from(self.ids.charwindow_frame, 20.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.questlog_frame, ui_widgets);
} else {
Image::new(self.imgs.window_frame)
.top_left_with_margins_on(ui_widgets.window, 200.0, 10.0)
.w_h(107.0 * 4.0, 125.0 * 4.0)
.set(self.ids.questlog_frame, ui_widgets);
}
// Icon
Image::new(self.imgs.questlog_icon)
.w_h(40.0, 40.0)
.top_left_with_margins_on(self.ids.questlog_frame, 4.0, 4.0)
.set(self.ids.questlog_icon, ui_widgets);
// Content alignment
Rectangle::fill_with([362.0, 418.0], color::TRANSPARENT)
.bottom_right_with_margins_on(self.ids.questlog_frame, 17.0, 17.0)
.scroll_kids()
.scroll_kids_vertically()
.set(self.ids.questlog_bg, ui_widgets);
// X-Button
if Button::image(self.imgs.close_button)
.w_h(20.0, 20.0)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(self.ids.questlog_frame, 17.0, 5.0)
.set(self.ids.questlog_close, ui_widgets)
.was_clicked()
{
self.open_windows = match self.open_windows {
Windows::Small(_) => Windows::None,
Windows::CharacterAnd(_) => Windows::CharacterAnd(None),
_ => Windows::Settings,
}
}
// Title
Text::new("Quest-Log")
.mid_top_with_margin_on(self.ids.questlog_frame, 17.0)
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.questlog_title, ui_widgets);
}
match SmallWindow::new(small, &self.imgs, &self.fonts)
.top_left_with_margins_on(ui_widgets.window, 200.0, 215.0)
.w_h(103.0 * 4.0, 122.0 * 4.0) // TODO: replace this with default_width() / height() overrides
.set(self.ids.small_window, ui_widgets)
{
Some(small_window::Event::Close) => self.open_windows = match self.open_windows {
Windows::Small(_) => Windows::None,
Windows::CharacterAnd(_) => Windows::CharacterAnd(None),
_ => Windows::Settings,
},
None => {}
}
}
@ -1268,7 +767,7 @@ impl Hud {
Some(small) => Windows::Small(small),
None => Windows::None,
},
None => {},
None => {}
}
}
@ -1279,22 +778,37 @@ impl Hud {
.set(self.ids.map, ui_widgets)
{
Some(map::Event::Close) => self.map_open = false,
None => {},
None => {}
}
}
// ESC-MENU
// Background
// Esc-menu
if self.esc_menu_open {
match EscMenu::new(&self.imgs, &self.fonts)
.top_left_with_margins_on(ui_widgets.window, 200.0, 215.0)
.set(self.ids.esc_menu, ui_widgets)
{
Some(esc_menu::Event::OpenSettings) => {
self.esc_menu_open = false;
self.open_windows = Windows::Settings;
}
Some(esc_menu::Event::Close) => self.esc_menu_open = false,
Some(esc_menu::Event::Logout) => events.push(Event::Logout),
Some(esc_menu::Event::Quit) => events.push(Event::Quit),
None => {},
}
}
events
}
pub fn new_message(&mut self, msg: String) {
self.chat.new_message(msg);
self.new_messages.push_back(msg);
}
fn toggle_menu(&mut self) {
self.menu_open = !self.menu_open;
self.esc_menu_open = !self.esc_menu_open;
}
fn toggle_bag(&mut self) {
self.bag_open = !self.bag_open
@ -1305,11 +819,11 @@ impl Hud {
}
fn toggle_questlog(&mut self) {
self.open_windows = match self.open_windows {
Windows::Small(Small::Questlog) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Questlog),
Windows::Small(SmallWindowType::Questlog) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Questlog),
Windows::CharacterAnd(small) => match small {
Some(Small::Questlog) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Questlog)),
Some(SmallWindowType::Questlog) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Questlog)),
},
Windows::Settings => Windows::Settings,
};
@ -1327,22 +841,22 @@ impl Hud {
}
fn toggle_social(&mut self) {
self.open_windows = match self.open_windows {
Windows::Small(Small::Social) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Social),
Windows::Small(SmallWindowType::Social) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Social),
Windows::CharacterAnd(small) => match small {
Some(Small::Social) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Social)),
Some(SmallWindowType::Social) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Social)),
},
Windows::Settings => Windows::Settings,
};
}
fn toggle_spellbook(&mut self) {
self.open_windows = match self.open_windows {
Windows::Small(Small::Spellbook) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(Small::Spellbook),
Windows::Small(SmallWindowType::Spellbook) => Windows::None,
Windows::None | Windows::Small(_) => Windows::Small(SmallWindowType::Spellbook),
Windows::CharacterAnd(small) => match small {
Some(Small::Spellbook) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(Small::Spellbook)),
Some(SmallWindowType::Spellbook) => Windows::CharacterAnd(None),
_ => Windows::CharacterAnd(Some(SmallWindowType::Spellbook)),
},
Windows::Settings => Windows::Settings,
};
@ -1363,7 +877,7 @@ impl Hud {
fn toggle_windows(&mut self, global_state: &mut GlobalState) {
if self.bag_open
|| self.menu_open
|| self.esc_menu_open
|| self.map_open
|| match self.open_windows {
Windows::None => false,
@ -1371,19 +885,19 @@ impl Hud {
}
{
self.bag_open = false;
self.menu_open = false;
self.esc_menu_open = false;
self.map_open = false;
self.open_windows = Windows::None;
global_state.window.grab_cursor(true);
} else {
self.menu_open = true;
self.esc_menu_open = true;
global_state.window.grab_cursor(false);
}
}
fn typing(&self) -> bool {
match self.ui.widget_capturing_keyboard() {
Some(id) if id == self.chat.input_box_id() => true,
Some(id) if id == self.ids.chat => true,
_ => false,
}
}
@ -1406,11 +920,7 @@ impl Hud {
_ if !self.show_ui => false,
WinEvent::Zoom(_) => !cursor_grabbed && !self.ui.no_widget_capturing_mouse(),
WinEvent::KeyDown(Key::Enter) => {
self.ui.focus_widget(if self.typing() {
None
} else {
Some(self.chat.input_box_id())
});
self.ui.focus_widget(Some(self.ids.chat));
true
}
WinEvent::KeyDown(Key::Escape) => {

View File

@ -0,0 +1,308 @@
use conrod_core::{
builder_methods, color,
text::font,
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use super::{
img_ids::Imgs,
font_ids::Fonts,
TEXT_COLOR,
};
use crate::ui::ToggleButton;
widget_ids! {
struct Ids {
button_help,
controls,
debug_button,
debug_button_label,
gameplay,
interface,
inventorytest_button,
inventorytest_button_label,
rectangle,
settings_bg,
settings_close,
settings_icon,
settings_title,
show_help_label,
sound,
test,
video,
}
}
enum SettingsTab {
Interface,
Video,
Sound,
Gameplay,
Controls,
}
#[derive(WidgetCommon)]
pub struct SettingsWindow<'a> {
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
common: widget::CommonBuilder,
style: (),
}
impl<'a> SettingsWindow<'a> {
pub fn new(imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
Self {
imgs,
fonts,
common: widget::CommonBuilder::default(),
style: (),
}
}
}
pub struct State {
settings_tab: SettingsTab,
show_debug: bool,
show_help: bool,
inventorytest_button: bool,
ids: Ids,
}
pub enum Event {
Close,
}
impl<'a> Widget for SettingsWindow<'a> {
type State = State;
type Style = ();
type Event = Option<Event>;
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
settings_tab: SettingsTab::Interface,
show_debug: false,
show_help: false,
inventorytest_button: false,
ids: Ids::new(id_gen),
}
}
fn style(&self) -> Self::Style {
()
}
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
let widget::UpdateArgs {
id,
state,
ui,
style,
..
} = args;
// BG
Image::new(self.imgs.settings_bg)
.middle_of(ui.window)
.w_h(1648.0 / 2.5, 1952.0 / 2.5)
.set(state.ids.settings_bg, ui);
// X-Button
if Button::image(self.imgs.close_button)
.w_h(244.0 * 0.22 / 2.5, 244.0 * 0.22 / 2.5)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(state.ids.settings_bg, 4.0, 4.0)
.set(state.ids.settings_close, ui)
.was_clicked()
{
return Some(Event::Close);
}
// Title
Text::new("Settings")
.mid_top_with_margin_on(state.ids.settings_bg, 10.0)
.font_size(30)
.color(TEXT_COLOR)
.set(state.ids.settings_title, ui);
// Icon
Image::new(self.imgs.settings_icon)
.w_h(224.0 / 3.0, 224.0 / 3.0)
.top_left_with_margins_on(state.ids.settings_bg, -10.0, -10.0)
.set(state.ids.settings_icon, ui);
// TODO: Find out if we can remove this
// Alignment Rectangle
Rectangle::fill_with([1008.0 / 2.5, 1616.0 / 2.5], color::TRANSPARENT)
.top_left_with_margins_on(state.ids.settings_bg, 77.0, 205.0)
.set(state.ids.rectangle, ui);
// Interface
if Button::image(if let SettingsTab::Interface = state.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
})
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.top_left_with_margins_on(state.ids.settings_bg, 78.0, 50.0)
.label("Interface")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(state.ids.interface, ui)
.was_clicked()
{
state.update(|s| s.settings_tab = SettingsTab::Interface);
}
// Toggle Help
if let SettingsTab::Interface = state.settings_tab {
let show_debug =
ToggleButton::new(state.show_help, self.imgs.check, self.imgs.check_checked)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.top_left_with_margins_on(state.ids.rectangle, 15.0, 15.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(state.ids.button_help, ui);
state.update(|s| s.show_debug = show_debug);
Text::new("Show Help")
.right_from(state.ids.button_help, 10.0)
.font_size(12)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.button_help)
.color(TEXT_COLOR)
.set(state.ids.show_help_label, ui);
let show_debug = ToggleButton::new(
state.inventorytest_button,
self.imgs.check,
self.imgs.check_checked,
)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.top_left_with_margins_on(state.ids.rectangle, 40.0, 15.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(state.ids.inventorytest_button, ui);
state.update(|s| s.show_debug = show_debug);
Text::new("Show Inventory Test Button")
.right_from(state.ids.inventorytest_button, 10.0)
.font_size(12)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.inventorytest_button)
.color(TEXT_COLOR)
.set(state.ids.inventorytest_button_label, ui);
let show_debug = ToggleButton::new(
state.show_debug,
self.imgs.check,
self.imgs.check_checked
)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.top_left_with_margins_on(state.ids.rectangle, 65.0, 15.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(state.ids.debug_button, ui);
state.update(|s| s.show_debug = show_debug);
Text::new("Show Debug Window")
.right_from(state.ids.debug_button, 10.0)
.font_size(12)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.debug_button)
.color(TEXT_COLOR)
.set(state.ids.debug_button_label, ui);
}
// 2 Gameplay////////////////
if Button::image(if let SettingsTab::Gameplay = state.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
}
)
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.down_from(state.ids.interface, 1.0)
.label("Gameplay")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(state.ids.gameplay, ui)
.was_clicked()
{
state.update(|s| s.settings_tab = SettingsTab::Gameplay);
}
// 3 Controls/////////////////////
if Button::image(if let SettingsTab::Controls = state.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
}
)
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.down_from(state.ids.gameplay, 1.0)
.label("Controls")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(state.ids.controls, ui)
.was_clicked()
{
state.update(|s| s.settings_tab = SettingsTab::Controls);
}
// 4 Video////////////////////////////////
if Button::image(if let SettingsTab::Video = state.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
}
)
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.down_from(state.ids.controls, 1.0)
.label("Video")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(state.ids.video, ui)
.was_clicked()
{
state.update(|s| s.settings_tab = SettingsTab::Video);
}
// 5 Sound///////////////////////////////
if Button::image(if let SettingsTab::Sound = state.settings_tab {
self.imgs.button_blue_mo
} else {
self.imgs.blank
}
)
.w_h(304.0 / 2.5, 80.0 / 2.5)
.hover_image(self.imgs.button_blue_mo)
.press_image(self.imgs.button_blue_press)
.down_from(state.ids.video, 1.0)
.label("Sound")
.label_font_size(14)
.label_color(TEXT_COLOR)
.set(state.ids.sound, ui)
.was_clicked()
{
state.update(|s| s.settings_tab = SettingsTab::Sound);
}
None
}
}

View File

@ -0,0 +1,149 @@
use conrod_core::{
builder_methods, color,
text::font,
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use super::{
img_ids::Imgs,
font_ids::Fonts,
TEXT_COLOR,
};
widget_ids! {
struct Ids {
frame,
bg,
title,
icon,
close,
}
}
#[derive(Clone, Copy)]
pub enum SmallWindowType {
Spellbook,
Social,
Questlog,
}
#[derive(WidgetCommon)]
pub struct SmallWindow<'a> {
content: SmallWindowType,
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
common: widget::CommonBuilder,
style: (),
}
impl<'a> SmallWindow<'a> {
pub fn new(content: SmallWindowType, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
Self {
content,
imgs,
fonts,
common: widget::CommonBuilder::default(),
style: (),
}
}
}
pub struct State {
ids: Ids,
}
pub enum Event {
Close,
}
impl<'a> Widget for SmallWindow<'a> {
type State = State;
type Style = ();
type Event = Option<Event>;
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>) -> Self::Event {
let widget::UpdateArgs {
id,
state,
ui,
style,
..
} = 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 true { //char_window_open {
Image::new(self.imgs.window_frame)
// TODO: Position
// .right_from(state.ids.character_window, 20.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(1648.0 / 4.0, 1952.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(20.0, 20.0)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(state.ids.frame, 17.0, 5.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
}
}