imgui-glutin-support crate

This commit is contained in:
Joonas Javanainen 2018-08-13 23:04:36 +03:00
parent b8a1abf1b7
commit eeb800db13
No known key found for this signature in database
GPG Key ID: D39CCA5CB19B9179
4 changed files with 242 additions and 1 deletions

View File

@ -5,6 +5,7 @@
### Added
- `ImGui::mouse_down`
- `imgui-glutin-support` crate
## [0.0.20] - 2018-08-13

View File

@ -16,4 +16,4 @@ travis-ci = { repository = "Gekkio/imgui-rs" }
imgui-sys = { version = "0.0.21-pre", path = "imgui-sys" }
[workspace]
members = ["imgui-examples", "imgui-sys", "imgui-gfx-renderer", "imgui-glium-renderer"]
members = ["imgui-examples", "imgui-sys", "imgui-gfx-renderer", "imgui-glium-renderer", "imgui-glutin-support"]

View File

@ -0,0 +1,16 @@
[package]
name = "imgui-glutin-support"
version = "0.0.21-pre"
authors = ["Joonas Javanainen <joonas.javanainen@gmail.com>", "imgui-rs contributors"]
description = "glutin support code for the imgui crate"
homepage = "https://github.com/Gekkio/imgui-rs"
repository = "https://github.com/Gekkio/imgui-rs"
license = "MIT/Apache-2.0"
categories = ["gui"]
[badges]
travis-ci = { repository = "Gekkio/imgui-rs" }
[dependencies]
glutin = "0.18"
imgui = { version = "0.0.21-pre", path = "../" }

View File

@ -0,0 +1,224 @@
//! This crate provides support functions to simplify integrating imgui-rs with glutin.
//!
//! # Using the library
//!
//! In your initialization code call `configure_keys`:
//!
//! ```
//! # extern crate imgui;
//! # extern crate imgui_glutin_support;
//! use imgui::ImGui;
//!
//! let mut imgui = ImGui::init();
//! imgui_glutin_support::configure_keys(&mut imgui);
//! ```
//!
//! In your main loop you should already be retrieving events from glutin and handling them. All
//! you need to do is pass each event to `imgui_glutin_support` as well:
//!
//! ```
//! # extern crate glutin;
//! # extern crate imgui;
//! # extern crate imgui_glutin_support;
//! # use glutin::EventsLoop;
//! # use imgui::ImGui;
//! # let mut events_loop = EventsLoop::new();
//! # let mut imgui = ImGui::init();
//! events_loop.poll_events(|event| {
//! // do application-specific stuff with event
//!
//! imgui_glutin_support::handle_event(&mut imgui, &event);
//! });
//! ```
//!
//! # Advanced use cases
//!
//! In more advanced use cases you might want to handle and filter events yourself and call some of
//! the various smaller helper functions exported by the library.
//!
//! For example, you might want to customize mouse wheel line scrolling amount:
//!
//! ```
//! # extern crate glutin;
//! # extern crate imgui;
//! # extern crate imgui_glutin_support;
//! # use glutin::{EventsLoop, Event, WindowEvent, MouseScrollDelta, TouchPhase};
//! # use imgui::ImGui;
//! # let mut events_loop = EventsLoop::new();
//! # let mut imgui = ImGui::init();
//! events_loop.poll_events(|event| {
//! // do application-specific stuff with event
//!
//! // default handling for events
//! imgui_glutin_support::handle_event(&mut imgui, &event);
//!
//! // Scroll 10 times the pixels per line by handling LineDelta events again and
//! // overriding the mouse wheel value
//! if let Event::WindowEvent { event, .. } = event {
//! match event {
//! WindowEvent::MouseWheel {
//! delta: MouseScrollDelta::LineDelta(_, lines),
//! phase: TouchPhase::Moved,
//! ..
//! } => {
//! imgui.set_mouse_wheel(lines * 10.0);
//! }
//! _ => ()
//! }
//! }
//! });
//! ```
extern crate glutin;
extern crate imgui;
use glutin::{
ElementState, Event, KeyboardInput, ModifiersState, MouseButton, MouseCursor, MouseScrollDelta,
TouchPhase, VirtualKeyCode, Window, WindowEvent,
};
use imgui::{FrameSize, ImGui, ImGuiKey, ImGuiMouseCursor};
/// Configure imgui key map with glutin `VirtualKeyCode` values
pub fn configure_keys(imgui: &mut ImGui) {
imgui.set_imgui_key(ImGuiKey::Tab, VirtualKeyCode::Tab as _);
imgui.set_imgui_key(ImGuiKey::LeftArrow, VirtualKeyCode::Left as _);
imgui.set_imgui_key(ImGuiKey::RightArrow, VirtualKeyCode::Right as _);
imgui.set_imgui_key(ImGuiKey::UpArrow, VirtualKeyCode::Up as _);
imgui.set_imgui_key(ImGuiKey::DownArrow, VirtualKeyCode::Down as _);
imgui.set_imgui_key(ImGuiKey::PageUp, VirtualKeyCode::PageUp as _);
imgui.set_imgui_key(ImGuiKey::PageDown, VirtualKeyCode::PageDown as _);
imgui.set_imgui_key(ImGuiKey::Home, VirtualKeyCode::Home as _);
imgui.set_imgui_key(ImGuiKey::End, VirtualKeyCode::End as _);
imgui.set_imgui_key(ImGuiKey::Delete, VirtualKeyCode::Delete as _);
imgui.set_imgui_key(ImGuiKey::Backspace, VirtualKeyCode::Back as _);
imgui.set_imgui_key(ImGuiKey::Enter, VirtualKeyCode::Return as _);
imgui.set_imgui_key(ImGuiKey::Escape, VirtualKeyCode::Escape as _);
imgui.set_imgui_key(ImGuiKey::A, VirtualKeyCode::A as _);
imgui.set_imgui_key(ImGuiKey::C, VirtualKeyCode::C as _);
imgui.set_imgui_key(ImGuiKey::V, VirtualKeyCode::V as _);
imgui.set_imgui_key(ImGuiKey::X, VirtualKeyCode::X as _);
imgui.set_imgui_key(ImGuiKey::Y, VirtualKeyCode::Y as _);
imgui.set_imgui_key(ImGuiKey::Z, VirtualKeyCode::Z as _);
}
/// Update imgui keyboard state
pub fn handle_keyboard_input(imgui: &mut ImGui, event: KeyboardInput) {
handle_modifiers(imgui, event.modifiers);
if let Some(key) = event.virtual_keycode {
let state_bool = event.state == ElementState::Pressed;
imgui.set_key(key as _, state_bool);
match key {
VirtualKeyCode::LShift | VirtualKeyCode::RShift => imgui.set_key_shift(state_bool),
VirtualKeyCode::LControl | VirtualKeyCode::RControl => imgui.set_key_ctrl(state_bool),
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => imgui.set_key_alt(state_bool),
VirtualKeyCode::LWin | VirtualKeyCode::RWin => imgui.set_key_super(state_bool),
_ => (),
}
}
}
/// Update imgui keyboard modifier state
pub fn handle_modifiers(imgui: &mut ImGui, modifiers: ModifiersState) {
imgui.set_key_shift(modifiers.shift);
imgui.set_key_ctrl(modifiers.ctrl);
imgui.set_key_alt(modifiers.alt);
imgui.set_key_super(modifiers.logo);
}
/// Update imgui mouse wheel position
pub fn handle_mouse_scroll_delta(imgui: &mut ImGui, delta: MouseScrollDelta) {
match delta {
MouseScrollDelta::LineDelta(_, y) => imgui.set_mouse_wheel(y),
MouseScrollDelta::PixelDelta(pos) => imgui.set_mouse_wheel(pos.y as f32),
}
}
/// Update imgui mouse button state
pub fn handle_mouse_button_state(imgui: &mut ImGui, button: MouseButton, state: ElementState) {
let mut states = imgui.mouse_down();
let state_bool = state == ElementState::Pressed;
match button {
MouseButton::Left => states[0] = state_bool,
MouseButton::Right => states[1] = state_bool,
MouseButton::Middle => states[2] = state_bool,
MouseButton::Other(idx @ 0...4) => states[idx as usize] = state_bool,
_ => (),
}
imgui.set_mouse_down(states);
}
/// Update imgui state from glutin event
pub fn handle_event(imgui: &mut ImGui, event: &Event) {
match event {
&Event::WindowEvent { ref event, .. } => handle_window_event(imgui, event),
_ => (),
}
}
/// Update imgui state from glutin window event
pub fn handle_window_event(imgui: &mut ImGui, event: &WindowEvent) {
use WindowEvent::*;
match event {
&KeyboardInput { input, .. } => handle_keyboard_input(imgui, input),
&ReceivedCharacter(ch) => imgui.add_input_character(ch),
&CursorMoved {
position,
modifiers,
..
} => {
imgui.set_mouse_pos(position.x as f32, position.y as f32);
handle_modifiers(imgui, modifiers);
}
&MouseWheel {
delta,
modifiers,
phase: TouchPhase::Moved,
..
} => {
handle_mouse_scroll_delta(imgui, delta);
handle_modifiers(imgui, modifiers);
}
&MouseInput {
state,
button,
modifiers,
..
} => {
handle_mouse_button_state(imgui, button, state);
handle_modifiers(imgui, modifiers);
}
_ => (),
}
}
/// Update glutin window mouse cursor state
pub fn update_mouse_cursor(imgui: &ImGui, window: &Window) {
let mouse_cursor = imgui.mouse_cursor();
if imgui.mouse_draw_cursor() || mouse_cursor == ImGuiMouseCursor::None {
// Hide OS cursor
window.hide_cursor(true);
} else {
// Set OS cursor
window.hide_cursor(false);
window.set_cursor(match mouse_cursor {
ImGuiMouseCursor::None => unreachable!("mouse_cursor was None!"),
ImGuiMouseCursor::Arrow => MouseCursor::Arrow,
ImGuiMouseCursor::TextInput => MouseCursor::Text,
ImGuiMouseCursor::Move => MouseCursor::Move,
ImGuiMouseCursor::ResizeNS => MouseCursor::NsResize,
ImGuiMouseCursor::ResizeEW => MouseCursor::EwResize,
ImGuiMouseCursor::ResizeNESW => MouseCursor::NeswResize,
ImGuiMouseCursor::ResizeNWSE => MouseCursor::NwseResize,
});
}
}
/// Get the current frame size for imgui frame rendering.
///
/// Returns `None` if the window no longer exists
pub fn get_frame_size(window: &mut Window) -> Option<FrameSize> {
window.get_inner_size().map(|logical_size| FrameSize {
logical_size: logical_size.into(),
hidpi_factor: window.get_hidpi_factor(),
})
}