make hud consume key events when typing in the chat box

Former-commit-id: bb1b06827d3d298f68ae6d17f534c7bc31065306
This commit is contained in:
Imbris 2019-03-21 23:55:42 -04:00
parent b0009f9e14
commit fdb0512069
11 changed files with 134 additions and 89 deletions

View File

@ -2,7 +2,7 @@ use crate::ui::Ui;
use conrod_core::{
input::Key,
position::Dimension,
widget::{List, Rectangle, Text, TextEdit},
widget::{Id, List, Rectangle, Text, TextEdit},
widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget,
};
use std::collections::VecDeque;
@ -31,6 +31,9 @@ impl Chat {
new_messages: false,
}
}
pub fn is_input_box(&self, id: Id) -> bool {
id == self.ids.input
}
pub fn new_message(&mut self, msg: String) {
self.messages.push_back(msg);
self.new_messages = true;

View File

@ -3,7 +3,7 @@ mod chat;
use crate::{
render::Renderer,
ui::{ScaleMode, Ui, ToggleButton},
window::Window,
window::{Event as WinEvent, Window, Key},
};
use conrod_core::{
event::Input,
@ -312,6 +312,8 @@ pub struct Hud {
ids: Ids,
imgs: Imgs,
chat: chat::Chat,
typing: bool,
cursor_grabbed: bool,
font_metamorph: FontId,
font_whitney: FontId,
show_help: bool,
@ -357,6 +359,8 @@ impl Hud {
imgs,
ids,
chat,
typing: false,
cursor_grabbed: true,
settings_tab: SettingsTab::Interface,
show_help: true,
bag_open: false,
@ -605,6 +609,26 @@ impl Hud {
//Debuffs
// Bag contents
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_on(ui_widgets.window, 88.0, 68.0)
.set(self.ids.bag_contents, ui_widgets);
// X-button
if Button::image(self.imgs.close_button)
.w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(self.ids.bag_contents, 5.0, 17.0)
.set(self.ids.bag_close, ui_widgets)
.was_clicked()
{
self.bag_open = false;
}
}
// Bag
if self.mmap_button_2 == false {
self.bag_open =
@ -621,26 +645,6 @@ impl Hud {
.w_h(420.0 / 4.0, 480.0 / 4.0)
.set(self.ids.bag_map_open, ui_widgets);
}
// Bag contents
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_on(ui_widgets.window, 88.0, 68.0)
.set(self.ids.bag_contents, ui_widgets);
// X-button
if Button::image(self.imgs.close_button)
.w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0)
.hover_image(self.imgs.close_button_hover)
.press_image(self.imgs.close_button_press)
.top_right_with_margins_on(self.ids.bag_contents, 5.0, 17.0)
.set(self.ids.bag_close, ui_widgets)
.was_clicked()
{
self.bag_open = false;
}
}
//Windows
@ -1066,6 +1070,13 @@ impl Hud {
events.push(Event::Quit);
};
}
// update whether keyboard is captured
self.typing = if let Some(widget_id) = ui_widgets.global_input().current.widget_capturing_keyboard {
self.chat.is_input_box(widget_id)
} else {
false
};
events
}
@ -1077,8 +1088,26 @@ impl Hud {
self.menu_open = !self.menu_open;
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
pub fn update_grab(&mut self, cursor_grabbed: bool) {
self.cursor_grabbed = cursor_grabbed;
}
pub fn handle_event(&mut self, event: WinEvent) -> bool {
match event {
WinEvent::Ui(event) => {
if !(self.cursor_grabbed && event.is_keyboard_or_mouse()) {
self.ui.handle_event(event);
}
true
},
_ if self.cursor_grabbed => false,
WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key {
Key::ToggleCursor => false,
_ => self.typing,
},
WinEvent::Char(_) => self.typing,
_ => false,
}
}
pub fn maintain(&mut self, renderer: &mut Renderer) -> Vec<Event> {

View File

@ -49,8 +49,8 @@ impl PlayState for CharSelectionState {
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);
Event::Ui(event) => {
self.char_selection_ui.handle_event(event);
}
// Ignore all other events
_ => {}

View File

@ -1,4 +1,4 @@
use crate::{render::Renderer, ui::Ui, window::Window};
use crate::{render::Renderer, ui::{self, Ui}, window::Window};
use conrod_core::{
event::Input,
image::Id as ImgId,
@ -36,8 +36,8 @@ impl CharSelectionUi {
.set(self.widget_id, &mut ui_cell);
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
pub fn handle_event(&mut self, event: ui::Event) {
self.ui.handle_event(event);
}
pub fn maintain(&mut self, renderer: &mut Renderer) {

View File

@ -44,8 +44,8 @@ impl PlayState for MainMenuState {
match event {
Event::Close => return PlayStateResult::Shutdown,
// Pass events to ui
Event::UiEvent(input) => {
self.main_menu_ui.handle_event(input);
Event::Ui(event) => {
self.main_menu_ui.handle_event(event);
}
// Ignore all other events
_ => {}

View File

@ -1,6 +1,6 @@
use crate::{
render::Renderer,
ui::{ScaleMode, Ui},
ui::{self, ScaleMode, Ui},
window::Window,
};
use conrod_core::{
@ -292,8 +292,8 @@ impl MainMenuUi {
events
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
pub fn handle_event(&mut self, event: ui::Event) {
self.ui.handle_event(event);
}
pub fn maintain(&mut self, renderer: &mut Renderer) -> Vec<Event> {

View File

@ -50,8 +50,8 @@ impl PlayState for TitleState {
)));
}
// Pass events to ui
Event::UiEvent(input) => {
self.title_ui.handle_event(input);
Event::Ui(event) => {
self.title_ui.handle_event(event);
}
// Ignore all other events
_ => {}

View File

@ -1,4 +1,4 @@
use crate::{render::Renderer, ui::Ui, window::Window};
use crate::{render::Renderer, ui::{self, Ui}, window::Window};
use conrod_core::{
event::Input,
image::Id as ImgId,
@ -37,8 +37,8 @@ impl TitleUi {
.set(self.widget_id, &mut ui_cell);
}
pub fn handle_event(&mut self, input: Input) {
self.ui.handle_event(input);
pub fn handle_event(&mut self, event: ui::Event) {
self.ui.handle_event(event);
}
pub fn maintain(&mut self, renderer: &mut Renderer) {

View File

@ -118,8 +118,11 @@ impl PlayState for SessionState {
// Handle window events
for event in global_state.window.fetch_events() {
// Pass all events to the ui first
if self.hud.handle_event(event.clone()) {
continue;
}
let _handled = match event {
Event::Close => return PlayStateResult::Shutdown,
// When 'q' is pressed, exit the session
Event::Char('q') => return PlayStateResult::Pop,
@ -130,6 +133,7 @@ impl PlayState for SessionState {
// Toggle cursor grabbing
Event::KeyDown(Key::ToggleCursor) => {
global_state.window.grab_cursor(!global_state.window.is_cursor_grabbed());
self.hud.update_grab(global_state.window.is_cursor_grabbed());
},
// Movement Key Pressed
Event::KeyDown(Key::MoveForward) => self.key_state.up = true,
@ -141,10 +145,6 @@ impl PlayState for SessionState {
Event::KeyUp(Key::MoveBack) => self.key_state.down = false,
Event::KeyUp(Key::MoveLeft) => self.key_state.left = false,
Event::KeyUp(Key::MoveRight) => self.key_state.right = false,
// Pass events to ui
Event::UiEvent(input) => {
self.hud.handle_event(input);
}
// Pass all other events to the scene
event => { self.scene.handle_input_event(event); },
};

View File

@ -1,4 +1,3 @@
// TODO: figure out proper way to propagate events down to the ui
mod widgets;
pub use widgets::toggle_button::ToggleButton;
@ -40,6 +39,21 @@ use crate::{
pub enum UiError {
RenderError(RenderError),
}
#[derive(Clone)]
pub struct Event(Input);
impl Event {
pub fn try_from(event: glutin::Event, window: &glutin::GlWindow) -> Option<Self> {
conrod_winit::convert_event(event, window.window()).map(|input| {
Self(input)
})
}
pub fn is_keyboard_or_mouse(&self) -> bool {
match self.0 {
Input::Press(_) | Input::Release(_) | Input::Motion(_) | Input::Touch(_) | Input::Text(_) => true,
_ => false,
}
}
}
pub struct Cache {
blank_texture: Texture<UiPipeline>,
@ -207,8 +221,8 @@ impl Ui {
self.ui.set_widgets()
}
pub fn handle_event(&mut self, event: Input) {
match event {
pub fn handle_event(&mut self, event: Event) {
match event.0 {
Input::Resize(w, h) => self.window_resized = Some(Vec2::new(w, h)),
Input::Touch(touch) => self.ui.handle_event(
Input::Touch(Touch {
@ -233,7 +247,7 @@ impl Ui {
_ => motion,
})
),
_ => self.ui.handle_event(event),
_ => self.ui.handle_event(event.0),
}
}

View File

@ -1,10 +1,5 @@
// Library
use glutin;
use gfx_window_glutin;
use vek::*;
use std::collections::HashMap;
// Crate
use crate::{
Error,
render::{
@ -12,6 +7,7 @@ use crate::{
TgtColorFmt,
TgtDepthFmt,
},
ui,
};
pub struct Window {
@ -83,48 +79,49 @@ impl Window {
let key_map = &self.key_map;
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()) {
events.push(Event::UiEvent(event));
}
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();
gfx_window_glutin::update_views(
&window,
&mut color_view,
&mut depth_view,
);
events.push(Event::Resize(Vec2::new(width as u32, height as u32)));
},
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
self.events_loop.poll_events(|event| {
// Get events for ui
if let Some(event) = ui::Event::try_from(event.clone(), &window) {
events.push(Event::Ui(event));
}
glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
Some(keycode) => match key_map.get(&keycode) {
Some(&key) => events.push(match input.state {
glutin::ElementState::Pressed => Event::KeyDown(key),
_ => Event::KeyUp(key),
}),
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();
gfx_window_glutin::update_views(
&window,
&mut color_view,
&mut depth_view,
);
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 {
glutin::ElementState::Pressed => Event::KeyDown(key),
_ => Event::KeyUp(key),
}),
_ => {},
},
_ => {},
},
_ => {},
},
_ => {},
},
glutin::Event::DeviceEvent { event, .. } => match event {
glutin::DeviceEvent::MouseMotion { delta: (dx, dy), .. } if cursor_grabbed =>
glutin::Event::DeviceEvent { event, .. } => match event {
glutin::DeviceEvent::MouseMotion { delta: (dx, dy), .. } if cursor_grabbed =>
events.push(Event::CursorPan(Vec2::new(dx as f32, dy as f32))),
glutin::DeviceEvent::MouseWheel {
delta: glutin::MouseScrollDelta::LineDelta(_x, y),
..
} if cursor_grabbed => events.push(Event::Zoom(y as f32)),
glutin::DeviceEvent::MouseWheel {
delta: glutin::MouseScrollDelta::LineDelta(_x, y),
..
} if cursor_grabbed => events.push(Event::Zoom(y as f32)),
_ => {},
},
_ => {},
},
_ => {},
}
});
events
}
@ -163,6 +160,7 @@ pub enum Key {
}
/// Represents an incoming event from the window
#[derive(Clone)]
pub enum Event {
/// The window has been requested to close.
Close,
@ -178,5 +176,6 @@ pub enum Event {
KeyDown(Key),
/// A key that the game recognises has been released down
KeyUp(Key),
UiEvent(conrod_core::event::Input)
/// Event that the ui uses
Ui(ui::Event),
}