diff --git a/Cargo.toml b/Cargo.toml index 1c2fa36..106669d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ default = ["glium"] libc = "0.1" [dependencies.glium] -version = "0.9" +version = "0.10" default-features = false optional = true @@ -30,6 +30,6 @@ gcc = "0.3" time = "0.1" [dev-dependencies.glium] -version = "0.9" +version = "0.10" features = ["glutin"] default-features = false diff --git a/examples/hello_world.rs b/examples/hello_world.rs index bb851a1..99c1c4e 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -16,7 +16,8 @@ fn main() { let mut support = Support::init(); loop { - let active = support.render(CLEAR_COLOR, hello_world); + support.render(CLEAR_COLOR, hello_world); + let active = support.update_events(); if !active { break } } } diff --git a/examples/support/mod.rs b/examples/support/mod.rs index fd64a5f..a7a6e58 100644 --- a/examples/support/mod.rs +++ b/examples/support/mod.rs @@ -1,8 +1,8 @@ use glium::{DisplayBuild, Surface}; use glium::backend::glutin_backend::GlutinFacade; use glium::glutin; -use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode}; -use imgui::{ImGui, Ui}; +use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, VirtualKeyCode}; +use imgui::{ImGui, Ui, ImGuiKey}; use imgui::glium_renderer::Renderer; use time::SteadyTime; @@ -12,7 +12,8 @@ pub struct Support { renderer: Renderer, last_frame: SteadyTime, mouse_pos: (i32, i32), - mouse_pressed: (bool, bool, bool) + mouse_pressed: (bool, bool, bool), + mouse_wheel: f32, } impl Support { @@ -24,29 +25,52 @@ impl Support { let mut imgui = ImGui::init(); let renderer = Renderer::init(&mut imgui, &display).unwrap(); + imgui.set_imgui_key(ImGuiKey::Tab, 0); + imgui.set_imgui_key(ImGuiKey::LeftArrow, 1); + imgui.set_imgui_key(ImGuiKey::RightArrow, 2); + imgui.set_imgui_key(ImGuiKey::UpArrow, 3); + imgui.set_imgui_key(ImGuiKey::DownArrow, 4); + imgui.set_imgui_key(ImGuiKey::PageUp, 5); + imgui.set_imgui_key(ImGuiKey::PageDown, 6); + imgui.set_imgui_key(ImGuiKey::Home, 7); + imgui.set_imgui_key(ImGuiKey::End, 8); + imgui.set_imgui_key(ImGuiKey::Delete, 9); + imgui.set_imgui_key(ImGuiKey::Backspace, 10); + imgui.set_imgui_key(ImGuiKey::Enter, 11); + imgui.set_imgui_key(ImGuiKey::Escape, 12); + imgui.set_imgui_key(ImGuiKey::A, 13); + imgui.set_imgui_key(ImGuiKey::C, 14); + imgui.set_imgui_key(ImGuiKey::V, 15); + imgui.set_imgui_key(ImGuiKey::X, 16); + imgui.set_imgui_key(ImGuiKey::Y, 17); + imgui.set_imgui_key(ImGuiKey::Z, 18); + Support { display: display, imgui: imgui, renderer: renderer, last_frame: SteadyTime::now(), mouse_pos: (0, 0), - mouse_pressed: (false, false, false) + mouse_pressed: (false, false, false), + mouse_wheel: 0.0 } } pub fn update_mouse(&mut self) { self.imgui.set_mouse_pos(self.mouse_pos.0 as f32, self.mouse_pos.1 as f32); self.imgui.set_mouse_down(&[self.mouse_pressed.0, self.mouse_pressed.1, self.mouse_pressed.2, false, false]); + self.imgui.set_mouse_wheel(self.mouse_wheel); } pub fn render<'ui, 'a: 'ui , F: FnMut(&Ui<'ui>)>( - &'a mut self, clear_color: (f32, f32, f32, f32), mut f: F) -> bool { + &'a mut self, clear_color: (f32, f32, f32, f32), mut f: F) { let now = SteadyTime::now(); let delta = now - self.last_frame; let delta_f = delta.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0; self.last_frame = now; self.update_mouse(); + self.mouse_wheel = 0.0; let mut target = self.display.draw(); target.clear_color(clear_color.0, clear_color.1, @@ -58,20 +82,54 @@ impl Support { self.renderer.render(&mut target, ui).unwrap(); target.finish().unwrap(); + } + pub fn update_events(&mut self) -> bool { for event in self.display.poll_events() { match event { - Event::Closed | - Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape)) - => return false, - Event::MouseMoved(pos) => self.mouse_pos = pos, - Event::MouseInput(state, MouseButton::Left) => - self.mouse_pressed.0 = state == ElementState::Pressed, - Event::MouseInput(state, MouseButton::Right) => - self.mouse_pressed.1 = state == ElementState::Pressed, - Event::MouseInput(state, MouseButton::Middle) => - self.mouse_pressed.2 = state == ElementState::Pressed, - _ => () + Event::Closed => return false, + Event::KeyboardInput(state, _, code) => { + let pressed = state == ElementState::Pressed; + match code { + Some(VirtualKeyCode::Tab) => self.imgui.set_key(0, pressed), + Some(VirtualKeyCode::Left) => self.imgui.set_key(1, pressed), + Some(VirtualKeyCode::Right) => self.imgui.set_key(2, pressed), + Some(VirtualKeyCode::Up) => self.imgui.set_key(3, pressed), + Some(VirtualKeyCode::Down) => self.imgui.set_key(4, pressed), + Some(VirtualKeyCode::PageUp) => self.imgui.set_key(5, pressed), + Some(VirtualKeyCode::PageDown) => self.imgui.set_key(6, pressed), + Some(VirtualKeyCode::Home) => self.imgui.set_key(7, pressed), + Some(VirtualKeyCode::End) => self.imgui.set_key(8, pressed), + Some(VirtualKeyCode::Delete) => self.imgui.set_key(9, pressed), + Some(VirtualKeyCode::Back) => self.imgui.set_key(10, pressed), + Some(VirtualKeyCode::Return) => self.imgui.set_key(11, pressed), + Some(VirtualKeyCode::Escape) => self.imgui.set_key(12, pressed), + Some(VirtualKeyCode::A) => self.imgui.set_key(13, pressed), + Some(VirtualKeyCode::C) => self.imgui.set_key(14, pressed), + Some(VirtualKeyCode::V) => self.imgui.set_key(15, pressed), + Some(VirtualKeyCode::X) => self.imgui.set_key(16, pressed), + Some(VirtualKeyCode::Y) => self.imgui.set_key(17, pressed), + Some(VirtualKeyCode::Z) => self.imgui.set_key(18, pressed), + Some(VirtualKeyCode::LControl) | Some(VirtualKeyCode::RControl) => + self.imgui.set_key_ctrl(pressed), + Some(VirtualKeyCode::LShift) | Some(VirtualKeyCode::RShift) => + self.imgui.set_key_shift(pressed), + Some(VirtualKeyCode::LAlt) | Some(VirtualKeyCode::RAlt) => + self.imgui.set_key_alt(pressed), + _ => {}, + } + }, + Event::MouseMoved(pos) => self.mouse_pos = pos, + Event::MouseInput(state, MouseButton::Left) => + self.mouse_pressed.0 = state == ElementState::Pressed, + Event::MouseInput(state, MouseButton::Right) => + self.mouse_pressed.1 = state == ElementState::Pressed, + Event::MouseInput(state, MouseButton::Middle) => + self.mouse_pressed.2 = state == ElementState::Pressed, + Event::MouseWheel(MouseScrollDelta::LineDelta(_, y)) => self.mouse_wheel = y, + Event::MouseWheel(MouseScrollDelta::PixelDelta(_, y)) => self.mouse_wheel = y, + Event::ReceivedCharacter(c) => self.imgui.add_input_character(c), + _ => () } } true diff --git a/examples/test_window.rs b/examples/test_window.rs index d185dc0..b79df03 100644 --- a/examples/test_window.rs +++ b/examples/test_window.rs @@ -8,16 +8,17 @@ use self::support::Support; mod support; -const CLEAR_COLOR: (f32, f32, f32, f32) = (1.0, 1.0, 1.0, 1.0); +const CLEAR_COLOR: (f32, f32, f32, f32) = (0.2, 0.2, 0.2, 1.0); fn main() { let mut support = Support::init(); loop { let mut open = true; - let active = support.render(CLEAR_COLOR, |ui| { + support.render(CLEAR_COLOR, |ui| { ui.show_test_window(&mut open) }); + let active = support.update_events(); if !active || !open { break } } } diff --git a/examples/test_window_impl.rs b/examples/test_window_impl.rs index 6dbdaa0..61c5344 100644 --- a/examples/test_window_impl.rs +++ b/examples/test_window_impl.rs @@ -92,9 +92,10 @@ fn main() { let mut opened = true; loop { - let active = support.render(state.clear_color, |ui| { + support.render(state.clear_color, |ui| { show_test_window(ui, &mut state, &mut opened); }); + let active = support.update_events(); if !active || !opened { break } } } diff --git a/imgui-sys/Cargo.toml b/imgui-sys/Cargo.toml index ac035d5..97e0c4a 100644 --- a/imgui-sys/Cargo.toml +++ b/imgui-sys/Cargo.toml @@ -16,7 +16,7 @@ bitflags = "0.3" libc = "0.1" [dependencies.glium] -version = "0.9" +version = "0.10" default-features = false optional = true diff --git a/src/glium_renderer.rs b/src/glium_renderer.rs index daab72f..2c932f7 100644 --- a/src/glium_renderer.rs +++ b/src/glium_renderer.rs @@ -17,7 +17,7 @@ pub type RendererResult = Result; pub enum RendererError { Vertex(vertex::BufferCreationError), Index(index::BufferCreationError), - Program(program::ProgramCreationError), + Program(program::ProgramChooserCreationError), Texture(texture::TextureCreationError), Draw(DrawError) } @@ -47,8 +47,8 @@ impl From for RendererError { } } -impl From for RendererError { - fn from(e: program::ProgramCreationError) -> RendererError { +impl From for RendererError { + fn from(e: program::ProgramChooserCreationError) -> RendererError { RendererError::Program(e) } } @@ -131,7 +131,7 @@ pub struct DeviceObjects { texture: Texture2d } -fn compile_default_program(ctx: &F) -> Result { +fn compile_default_program(ctx: &F) -> Result { program!( ctx, 140 => { diff --git a/src/lib.rs b/src/lib.rs index cc678e9..8539235 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,8 @@ pub use imgui_sys::{ ImGuiWindowFlags_NoScrollbar, ImGuiWindowFlags_NoScrollWithMouse, ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_AlwaysAutoResize, ImGuiWindowFlags_ShowBorders, ImGuiWindowFlags_NoSavedSettings, ImGuiWindowFlags_NoInputs, ImGuiWindowFlags_MenuBar, - ImVec2, ImVec4 + ImVec2, ImVec4, + ImGuiKey }; pub use menus::{Menu, MenuItem}; pub use sliders::{SliderFloat, SliderInt}; @@ -221,6 +222,28 @@ impl ImGui { let io = self.io_mut(); io.key_alt = value; } + pub fn set_key(&mut self, key: u8, pressed: bool) { + let io = self.io_mut(); + io.keys_down[key as usize] = pressed; + } + pub fn set_imgui_key(&mut self, key: ImGuiKey, mapping: u8) { + let io = self.io_mut(); + io.key_map[key as usize] = mapping as i32; + } + pub fn add_input_character(&mut self, character: char) { + if !character.is_control() { + // TODO: This is slightly better. We should use char::encode_utf8 when it stabilizes + // to allow us to skip the string intermediate since we can then go directly + // to bytes + let utf8_str: String = character.escape_default().collect(); + let mut bytes = utf8_str.into_bytes(); + // into_bytes does not produce a c-string, we must append the null terminator + bytes.push(0); + unsafe { + imgui_sys::ImGuiIO_AddInputCharactersUTF8(bytes.as_ptr() as *const i8); + } + } + } pub fn get_time(&self) -> f32 { unsafe { imgui_sys::igGetTime() } } pub fn get_frame_count(&self) -> i32 { unsafe { imgui_sys::igGetFrameCount() } } pub fn get_frame_rate(&self) -> f32 { self.io().framerate }