diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index d951ed5ea3..602ce51e34 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -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; diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 9459384626..f5c11fcc79 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -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 { diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index f2dc0e4cf8..689c1cf43c 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -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 _ => {} diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 02c7ea8e2f..cec090c7f7 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -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) { diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 9c4e7785e7..c32b2a3d5d 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -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 _ => {} diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 2745ebd560..1f57b116b7 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -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 { diff --git a/voxygen/src/menu/title/mod.rs b/voxygen/src/menu/title/mod.rs index 9ecb1aea52..0e8aa346bc 100644 --- a/voxygen/src/menu/title/mod.rs +++ b/voxygen/src/menu/title/mod.rs @@ -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 _ => {} diff --git a/voxygen/src/menu/title/ui.rs b/voxygen/src/menu/title/ui.rs index 42af907f5a..228f4ceb3d 100644 --- a/voxygen/src/menu/title/ui.rs +++ b/voxygen/src/menu/title/ui.rs @@ -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) { diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 53320f9d0d..f24fa2cd4e 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -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); }, }; diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 9399be660f..de433133dd 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -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 { + 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, @@ -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), } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index f71b9ae5fc..dcce0b31ad 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -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), }