Merge pull request #9 from Twinklebear/master

Support for Text Input
This commit is contained in:
Joonas Javanainen 2015-10-18 10:35:28 +03:00
commit 20bf8cd7f0
8 changed files with 112 additions and 28 deletions

View File

@ -15,7 +15,7 @@ default = ["glium"]
libc = "0.1" libc = "0.1"
[dependencies.glium] [dependencies.glium]
version = "0.9" version = "0.10"
default-features = false default-features = false
optional = true optional = true
@ -30,6 +30,6 @@ gcc = "0.3"
time = "0.1" time = "0.1"
[dev-dependencies.glium] [dev-dependencies.glium]
version = "0.9" version = "0.10"
features = ["glutin"] features = ["glutin"]
default-features = false default-features = false

View File

@ -16,7 +16,8 @@ fn main() {
let mut support = Support::init(); let mut support = Support::init();
loop { loop {
let active = support.render(CLEAR_COLOR, hello_world); support.render(CLEAR_COLOR, hello_world);
let active = support.update_events();
if !active { break } if !active { break }
} }
} }

View File

@ -1,8 +1,8 @@
use glium::{DisplayBuild, Surface}; use glium::{DisplayBuild, Surface};
use glium::backend::glutin_backend::GlutinFacade; use glium::backend::glutin_backend::GlutinFacade;
use glium::glutin; use glium::glutin;
use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode}; use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, VirtualKeyCode};
use imgui::{ImGui, Ui}; use imgui::{ImGui, Ui, ImGuiKey};
use imgui::glium_renderer::Renderer; use imgui::glium_renderer::Renderer;
use time::SteadyTime; use time::SteadyTime;
@ -12,7 +12,8 @@ pub struct Support {
renderer: Renderer, renderer: Renderer,
last_frame: SteadyTime, last_frame: SteadyTime,
mouse_pos: (i32, i32), mouse_pos: (i32, i32),
mouse_pressed: (bool, bool, bool) mouse_pressed: (bool, bool, bool),
mouse_wheel: f32,
} }
impl Support { impl Support {
@ -24,29 +25,52 @@ impl Support {
let mut imgui = ImGui::init(); let mut imgui = ImGui::init();
let renderer = Renderer::init(&mut imgui, &display).unwrap(); 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 { Support {
display: display, display: display,
imgui: imgui, imgui: imgui,
renderer: renderer, renderer: renderer,
last_frame: SteadyTime::now(), last_frame: SteadyTime::now(),
mouse_pos: (0, 0), mouse_pos: (0, 0),
mouse_pressed: (false, false, false) mouse_pressed: (false, false, false),
mouse_wheel: 0.0
} }
} }
pub fn update_mouse(&mut self) { 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_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_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>)>( 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 now = SteadyTime::now();
let delta = now - self.last_frame; let delta = now - self.last_frame;
let delta_f = delta.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0; let delta_f = delta.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0;
self.last_frame = now; self.last_frame = now;
self.update_mouse(); self.update_mouse();
self.mouse_wheel = 0.0;
let mut target = self.display.draw(); let mut target = self.display.draw();
target.clear_color(clear_color.0, clear_color.1, target.clear_color(clear_color.0, clear_color.1,
@ -58,20 +82,54 @@ impl Support {
self.renderer.render(&mut target, ui).unwrap(); self.renderer.render(&mut target, ui).unwrap();
target.finish().unwrap(); target.finish().unwrap();
}
pub fn update_events(&mut self) -> bool {
for event in self.display.poll_events() { for event in self.display.poll_events() {
match event { match event {
Event::Closed | Event::Closed => return false,
Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape)) Event::KeyboardInput(state, _, code) => {
=> return false, let pressed = state == ElementState::Pressed;
Event::MouseMoved(pos) => self.mouse_pos = pos, match code {
Event::MouseInput(state, MouseButton::Left) => Some(VirtualKeyCode::Tab) => self.imgui.set_key(0, pressed),
self.mouse_pressed.0 = state == ElementState::Pressed, Some(VirtualKeyCode::Left) => self.imgui.set_key(1, pressed),
Event::MouseInput(state, MouseButton::Right) => Some(VirtualKeyCode::Right) => self.imgui.set_key(2, pressed),
self.mouse_pressed.1 = state == ElementState::Pressed, Some(VirtualKeyCode::Up) => self.imgui.set_key(3, pressed),
Event::MouseInput(state, MouseButton::Middle) => Some(VirtualKeyCode::Down) => self.imgui.set_key(4, pressed),
self.mouse_pressed.2 = state == ElementState::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 true

View File

@ -8,16 +8,17 @@ use self::support::Support;
mod 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() { fn main() {
let mut support = Support::init(); let mut support = Support::init();
loop { loop {
let mut open = true; let mut open = true;
let active = support.render(CLEAR_COLOR, |ui| { support.render(CLEAR_COLOR, |ui| {
ui.show_test_window(&mut open) ui.show_test_window(&mut open)
}); });
let active = support.update_events();
if !active || !open { break } if !active || !open { break }
} }
} }

View File

@ -92,9 +92,10 @@ fn main() {
let mut opened = true; let mut opened = true;
loop { loop {
let active = support.render(state.clear_color, |ui| { support.render(state.clear_color, |ui| {
show_test_window(ui, &mut state, &mut opened); show_test_window(ui, &mut state, &mut opened);
}); });
let active = support.update_events();
if !active || !opened { break } if !active || !opened { break }
} }
} }

View File

@ -16,7 +16,7 @@ bitflags = "0.3"
libc = "0.1" libc = "0.1"
[dependencies.glium] [dependencies.glium]
version = "0.9" version = "0.10"
default-features = false default-features = false
optional = true optional = true

View File

@ -17,7 +17,7 @@ pub type RendererResult<T> = Result<T, RendererError>;
pub enum RendererError { pub enum RendererError {
Vertex(vertex::BufferCreationError), Vertex(vertex::BufferCreationError),
Index(index::BufferCreationError), Index(index::BufferCreationError),
Program(program::ProgramCreationError), Program(program::ProgramChooserCreationError),
Texture(texture::TextureCreationError), Texture(texture::TextureCreationError),
Draw(DrawError) Draw(DrawError)
} }
@ -47,8 +47,8 @@ impl From<index::BufferCreationError> for RendererError {
} }
} }
impl From<program::ProgramCreationError> for RendererError { impl From<program::ProgramChooserCreationError> for RendererError {
fn from(e: program::ProgramCreationError) -> RendererError { fn from(e: program::ProgramChooserCreationError) -> RendererError {
RendererError::Program(e) RendererError::Program(e)
} }
} }
@ -131,7 +131,7 @@ pub struct DeviceObjects {
texture: Texture2d texture: Texture2d
} }
fn compile_default_program<F: Facade>(ctx: &F) -> Result<Program, program::ProgramCreationError> { fn compile_default_program<F: Facade>(ctx: &F) -> Result<Program, program::ProgramChooserCreationError> {
program!( program!(
ctx, ctx,
140 => { 140 => {

View File

@ -26,7 +26,8 @@ pub use imgui_sys::{
ImGuiWindowFlags_NoScrollbar, ImGuiWindowFlags_NoScrollWithMouse, ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoScrollbar, ImGuiWindowFlags_NoScrollWithMouse, ImGuiWindowFlags_NoCollapse,
ImGuiWindowFlags_AlwaysAutoResize, ImGuiWindowFlags_ShowBorders, ImGuiWindowFlags_AlwaysAutoResize, ImGuiWindowFlags_ShowBorders,
ImGuiWindowFlags_NoSavedSettings, ImGuiWindowFlags_NoInputs, ImGuiWindowFlags_MenuBar, ImGuiWindowFlags_NoSavedSettings, ImGuiWindowFlags_NoInputs, ImGuiWindowFlags_MenuBar,
ImVec2, ImVec4 ImVec2, ImVec4,
ImGuiKey
}; };
pub use menus::{Menu, MenuItem}; pub use menus::{Menu, MenuItem};
pub use sliders::{SliderFloat, SliderInt}; pub use sliders::{SliderFloat, SliderInt};
@ -221,6 +222,28 @@ impl ImGui {
let io = self.io_mut(); let io = self.io_mut();
io.key_alt = value; 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_time(&self) -> f32 { unsafe { imgui_sys::igGetTime() } }
pub fn get_frame_count(&self) -> i32 { unsafe { imgui_sys::igGetFrameCount() } } pub fn get_frame_count(&self) -> i32 { unsafe { imgui_sys::igGetFrameCount() } }
pub fn get_frame_rate(&self) -> f32 { self.io().framerate } pub fn get_frame_rate(&self) -> f32 { self.io().framerate }