From 2ce985996a308aa3592a4b67684fd3d4a61dd0d9 Mon Sep 17 00:00:00 2001 From: dbr Date: Mon, 9 Jan 2023 20:06:58 +1030 Subject: [PATCH 1/6] Use event based IO for sdl2 mouse buttons --- imgui-sdl2-support/src/lib.rs | 61 ++++++----------------------------- 1 file changed, 9 insertions(+), 52 deletions(-) diff --git a/imgui-sdl2-support/src/lib.rs b/imgui-sdl2-support/src/lib.rs index a08ca5d..078a084 100644 --- a/imgui-sdl2-support/src/lib.rs +++ b/imgui-sdl2-support/src/lib.rs @@ -19,41 +19,11 @@ use imgui::{BackendFlags, ConfigFlags, Context, Io, Key, MouseCursor}; use sdl2::{ event::Event, keyboard::{Mod, Scancode}, - mouse::{Cursor, MouseButton, MouseState, SystemCursor}, + mouse::{Cursor, MouseState, SystemCursor}, video::Window, EventPump, }; -/// State of a single mouse button. Used so that we can detect cases where mouse -/// press and release occur on the same frame (seems surprisingly frequent on -/// macOS now...) -#[derive(Debug, Clone, Copy, Default)] -struct Button { - pub pressed_this_frame: bool, - state: bool, -} - -impl Button { - const fn new() -> Button { - Button { - pressed_this_frame: false, - state: false, - } - } - - fn get(&self) -> bool { - self.pressed_this_frame || self.state - } - - fn set(&mut self, pressed: bool) { - self.state = pressed; - - if pressed { - self.pressed_this_frame = true; - } - } -} - /// Handle changes in the key modifier states. fn handle_key_modifier(io: &mut Io, keymod: &Mod) { io.key_shift = keymod.intersects(Mod::LSHIFTMOD | Mod::RSHIFTMOD); @@ -109,7 +79,6 @@ pub fn filter_event(window: &Window, event: &Event) -> bool { pub struct SdlPlatform { cursor_instance: Option, /* to avoid dropping cursor instances */ last_frame: Instant, - mouse_buttons: [Button; 5], } impl SdlPlatform { @@ -157,7 +126,6 @@ impl SdlPlatform { SdlPlatform { cursor_instance: None, last_frame: Instant::now(), - mouse_buttons: [Button::new(); 5], } } @@ -178,12 +146,12 @@ impl SdlPlatform { } Event::MouseButtonDown { mouse_btn, .. } => { - self.handle_mouse_button(&mouse_btn, true); + self.handle_mouse_button(io, &mouse_btn, true); true } Event::MouseButtonUp { mouse_btn, .. } => { - self.handle_mouse_button(&mouse_btn, false); + self.handle_mouse_button(io, &mouse_btn, false); true } @@ -252,16 +220,6 @@ impl SdlPlatform { (window_drawable_size.1 as f32) / (window_size.1 as f32), ]; - // Update mouse button state - for (io_down, button) in io.mouse_down.iter_mut().zip(&mut self.mouse_buttons) { - *io_down = button.get(); - - // this frame is now "over" and we can set pressed_this_frame to false, but - // the state cannot be set to false due to actions that require multi-frame inputs - // ie: dragging, resizing and this is handled by the `MouseButtonDown` event. - button.pressed_this_frame = false; - } - // Set mouse position if requested by imgui-rs if io.want_set_mouse_pos { let mouse_util = window.subsystem().sdl().mouse(); @@ -297,14 +255,13 @@ impl SdlPlatform { } impl SdlPlatform { - fn handle_mouse_button(&mut self, button: &MouseButton, pressed: bool) { + fn handle_mouse_button(&mut self, io: &mut Io, button: &sdl2::mouse::MouseButton, pressed: bool) { match button { - MouseButton::Left => self.mouse_buttons[0].set(pressed), - MouseButton::Right => self.mouse_buttons[1].set(pressed), - MouseButton::Middle => self.mouse_buttons[2].set(pressed), - MouseButton::X1 => self.mouse_buttons[3].set(pressed), - MouseButton::X2 => self.mouse_buttons[4].set(pressed), - + sdl2::mouse::MouseButton::Left => io.add_mouse_button_event(imgui::MouseButton::Left, pressed), + sdl2::mouse::MouseButton::Right => io.add_mouse_button_event(imgui::MouseButton::Right, pressed), + sdl2::mouse::MouseButton::Middle => io.add_mouse_button_event(imgui::MouseButton::Middle, pressed), + sdl2::mouse::MouseButton::X1 => io.add_mouse_button_event(imgui::MouseButton::Extra1, pressed), + sdl2::mouse::MouseButton::X2 => io.add_mouse_button_event(imgui::MouseButton::Extra2, pressed), _ => {} } } From 09a83bac6c16c8d6fee1bb4633db9fdfc7c7da36 Mon Sep 17 00:00:00 2001 From: dbr Date: Mon, 9 Jan 2023 20:08:04 +1030 Subject: [PATCH 2/6] Update mouse wheel event --- imgui-sdl2-support/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui-sdl2-support/src/lib.rs b/imgui-sdl2-support/src/lib.rs index 078a084..1f5b3dc 100644 --- a/imgui-sdl2-support/src/lib.rs +++ b/imgui-sdl2-support/src/lib.rs @@ -140,8 +140,7 @@ impl SdlPlatform { match *event { Event::MouseWheel { x, y, .. } => { - io.mouse_wheel = y as f32; - io.mouse_wheel_h = x as f32; + io.add_mouse_wheel_event([x as f32, y as f32]); true } From 904d2a072f524c4776b105f646c9cfb186058a6f Mon Sep 17 00:00:00 2001 From: dbr Date: Tue, 10 Jan 2023 11:54:36 +1030 Subject: [PATCH 3/6] Update key handling to be event-based --- imgui-sdl2-support/src/lib.rs | 144 ++++++++++++++++++++++++++++------ 1 file changed, 119 insertions(+), 25 deletions(-) diff --git a/imgui-sdl2-support/src/lib.rs b/imgui-sdl2-support/src/lib.rs index 1f5b3dc..7c88759 100644 --- a/imgui-sdl2-support/src/lib.rs +++ b/imgui-sdl2-support/src/lib.rs @@ -24,6 +24,123 @@ use sdl2::{ EventPump, }; +/// Handle changes in the key states. +fn handle_key(io: &mut Io, key: &Scancode, pressed: bool) { + let igkey = match key { + Scancode::A => imgui::Key::A, + Scancode::B => imgui::Key::B, + Scancode::C => imgui::Key::C, + Scancode::D => imgui::Key::D, + Scancode::E => imgui::Key::E, + Scancode::F => imgui::Key::F, + Scancode::G => imgui::Key::G, + Scancode::H => imgui::Key::H, + Scancode::I => imgui::Key::I, + Scancode::J => imgui::Key::J, + Scancode::K => imgui::Key::K, + Scancode::L => imgui::Key::L, + Scancode::M => imgui::Key::M, + Scancode::N => imgui::Key::N, + Scancode::O => imgui::Key::O, + Scancode::P => imgui::Key::P, + Scancode::Q => imgui::Key::Q, + Scancode::R => imgui::Key::R, + Scancode::S => imgui::Key::S, + Scancode::T => imgui::Key::T, + Scancode::U => imgui::Key::U, + Scancode::V => imgui::Key::V, + Scancode::W => imgui::Key::W, + Scancode::X => imgui::Key::X, + Scancode::Y => imgui::Key::Y, + Scancode::Z => imgui::Key::Z, + Scancode::Num1 => imgui::Key::Keypad1, + Scancode::Num2 => imgui::Key::Keypad2, + Scancode::Num3 => imgui::Key::Keypad3, + Scancode::Num4 => imgui::Key::Keypad4, + Scancode::Num5 => imgui::Key::Keypad5, + Scancode::Num6 => imgui::Key::Keypad6, + Scancode::Num7 => imgui::Key::Keypad7, + Scancode::Num8 => imgui::Key::Keypad8, + Scancode::Num9 => imgui::Key::Keypad9, + Scancode::Num0 => imgui::Key::Keypad0, + Scancode::Return => imgui::Key::Enter, // TODO: Should this be treated as alias? + Scancode::Escape => imgui::Key::Escape, + Scancode::Backspace => imgui::Key::Backspace, + Scancode::Tab => imgui::Key::Tab, + Scancode::Space => imgui::Key::Space, + Scancode::Minus => imgui::Key::Minus, + Scancode::Equals => imgui::Key::Equal, + Scancode::LeftBracket => imgui::Key::LeftBracket, + Scancode::RightBracket => imgui::Key::RightBracket, + Scancode::Backslash => imgui::Key::Backslash, + Scancode::Semicolon => imgui::Key::Semicolon, + Scancode::Apostrophe => imgui::Key::Apostrophe, + Scancode::Grave => imgui::Key::GraveAccent, + Scancode::Comma => imgui::Key::Comma, + Scancode::Period => imgui::Key::Period, + Scancode::Slash => imgui::Key::Slash, + Scancode::CapsLock => imgui::Key::CapsLock, + Scancode::F1 => imgui::Key::F1, + Scancode::F2 => imgui::Key::F2, + Scancode::F3 => imgui::Key::F3, + Scancode::F4 => imgui::Key::F4, + Scancode::F5 => imgui::Key::F5, + Scancode::F6 => imgui::Key::F6, + Scancode::F7 => imgui::Key::F7, + Scancode::F8 => imgui::Key::F8, + Scancode::F9 => imgui::Key::F9, + Scancode::F10 => imgui::Key::F10, + Scancode::F11 => imgui::Key::F11, + Scancode::F12 => imgui::Key::F12, + Scancode::PrintScreen => imgui::Key::PrintScreen, + Scancode::ScrollLock => imgui::Key::ScrollLock, + Scancode::Pause => imgui::Key::Pause, + Scancode::Insert => imgui::Key::Insert, + Scancode::Home => imgui::Key::Home, + Scancode::PageUp => imgui::Key::PageUp, + Scancode::Delete => imgui::Key::Delete, + Scancode::End => imgui::Key::End, + Scancode::PageDown => imgui::Key::PageDown, + Scancode::Right => imgui::Key::RightArrow, + Scancode::Left => imgui::Key::LeftArrow, + Scancode::Down => imgui::Key::DownArrow, + Scancode::Up => imgui::Key::UpArrow, + Scancode::KpDivide => imgui::Key::KeypadDivide, + Scancode::KpMultiply => imgui::Key::KeypadMultiply, + Scancode::KpMinus => imgui::Key::KeypadSubtract, + Scancode::KpPlus => imgui::Key::KeypadAdd, + Scancode::KpEnter => imgui::Key::KeypadEnter, + Scancode::Kp1 => imgui::Key::Keypad1, + Scancode::Kp2 => imgui::Key::Keypad2, + Scancode::Kp3 => imgui::Key::Keypad3, + Scancode::Kp4 => imgui::Key::Keypad4, + Scancode::Kp5 => imgui::Key::Keypad5, + Scancode::Kp6 => imgui::Key::Keypad6, + Scancode::Kp7 => imgui::Key::Keypad7, + Scancode::Kp8 => imgui::Key::Keypad8, + Scancode::Kp9 => imgui::Key::Keypad9, + Scancode::Kp0 => imgui::Key::Keypad0, + Scancode::KpPeriod => imgui::Key::KeypadDecimal, + Scancode::Application => imgui::Key::Menu, + Scancode::KpEquals => imgui::Key::KeypadEqual, + Scancode::Menu => imgui::Key::Menu, + Scancode::LCtrl => imgui::Key::LeftCtrl, + Scancode::LShift => imgui::Key::LeftShift, + Scancode::LAlt => imgui::Key::LeftAlt, + Scancode::LGui => imgui::Key::LeftSuper, + Scancode::RCtrl => imgui::Key::RightCtrl, + Scancode::RShift => imgui::Key::RightShift, + Scancode::RAlt => imgui::Key::RightAlt, + Scancode::RGui => imgui::Key::RightSuper, + _ => { + // Ignore unknown keys + return; + } + }; + + io.add_key_event(igkey, pressed); +} + /// Handle changes in the key modifier states. fn handle_key_modifier(io: &mut Io, keymod: &Mod) { io.key_shift = keymod.intersects(Mod::LSHIFTMOD | Mod::RSHIFTMOD); @@ -95,29 +212,6 @@ impl SdlPlatform { io.backend_flags.insert(BackendFlags::HAS_MOUSE_CURSORS); io.backend_flags.insert(BackendFlags::HAS_SET_MOUSE_POS); - io[Key::Tab] = Scancode::Tab as _; - io[Key::LeftArrow] = Scancode::Left as _; - io[Key::RightArrow] = Scancode::Right as _; - io[Key::UpArrow] = Scancode::Up as _; - io[Key::DownArrow] = Scancode::Down as _; - io[Key::PageUp] = Scancode::PageUp as _; - io[Key::PageDown] = Scancode::PageDown as _; - io[Key::Home] = Scancode::Home as _; - io[Key::End] = Scancode::End as _; - io[Key::Insert] = Scancode::Insert as _; - io[Key::Delete] = Scancode::Delete as _; - io[Key::Backspace] = Scancode::Backspace as _; - io[Key::Space] = Scancode::Space as _; - io[Key::Enter] = Scancode::Return as _; - io[Key::Escape] = Scancode::Escape as _; - io[Key::KeypadEnter] = Scancode::KpEnter as _; - io[Key::A] = Scancode::A as _; - io[Key::C] = Scancode::C as _; - io[Key::V] = Scancode::V as _; - io[Key::X] = Scancode::X as _; - io[Key::Y] = Scancode::Y as _; - io[Key::Z] = Scancode::Z as _; - imgui.set_platform_name(Some(format!( "imgui-sdl2-support {}", env!("CARGO_PKG_VERSION") @@ -164,8 +258,8 @@ impl SdlPlatform { keymod, .. } => { - io.keys_down[key as usize] = true; handle_key_modifier(io, &keymod); + handle_key(io, &key, true); true } @@ -174,8 +268,8 @@ impl SdlPlatform { keymod, .. } => { - io.keys_down[key as usize] = false; handle_key_modifier(io, &keymod); + handle_key(io, &key, false); true } From 57267d5a4f6c059b8b93efe0913af7278356fb7a Mon Sep 17 00:00:00 2001 From: dbr Date: Tue, 10 Jan 2023 11:58:16 +1030 Subject: [PATCH 4/6] Bunch more comments in sdl2 example --- imgui-sdl2-support/examples/basic.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/imgui-sdl2-support/examples/basic.rs b/imgui-sdl2-support/examples/basic.rs index 4180f78..f89ea26 100644 --- a/imgui-sdl2-support/examples/basic.rs +++ b/imgui-sdl2-support/examples/basic.rs @@ -45,7 +45,10 @@ fn main() { /* create new glow and imgui contexts */ let gl = glow_context(&window); + /* create context */ let mut imgui = Context::create(); + + /* disable creation of files on disc */ imgui.set_ini_filename(None); imgui.set_log_filename(None); @@ -54,8 +57,11 @@ fn main() { .fonts() .add_font(&[imgui::FontSource::DefaultFontData { config: None }]); + /* create platform and renderer */ let mut platform = SdlPlatform::init(&mut imgui); let mut renderer = AutoRenderer::initialize(gl, &mut imgui).unwrap(); + + /* start main loop */ let mut event_pump = sdl.event_pump().unwrap(); 'main: loop { @@ -72,8 +78,10 @@ fn main() { platform.prepare_frame(&mut imgui, &window, &event_pump); let ui = imgui.new_frame(); + /* create imgui UI here */ ui.show_demo_window(&mut true); + /* render */ let draw_data = imgui.render(); unsafe { renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) }; From a50460405e918c57bbc21b88472b5474e2302a45 Mon Sep 17 00:00:00 2001 From: dbr Date: Tue, 10 Jan 2023 11:59:42 +1030 Subject: [PATCH 5/6] Rename sdl2-support example Running 'cargo --example' listed it as just 'basic' which is ambigious --- imgui-sdl2-support/examples/{basic.rs => sdl2_01_basic.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename imgui-sdl2-support/examples/{basic.rs => sdl2_01_basic.rs} (100%) diff --git a/imgui-sdl2-support/examples/basic.rs b/imgui-sdl2-support/examples/sdl2_01_basic.rs similarity index 100% rename from imgui-sdl2-support/examples/basic.rs rename to imgui-sdl2-support/examples/sdl2_01_basic.rs From a126e2086ec202da0a3e3e03fef4756bb302bde9 Mon Sep 17 00:00:00 2001 From: dbr Date: Tue, 10 Jan 2023 12:02:51 +1030 Subject: [PATCH 6/6] Tidying --- imgui-sdl2-support/src/lib.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/imgui-sdl2-support/src/lib.rs b/imgui-sdl2-support/src/lib.rs index 7c88759..eaee2d2 100644 --- a/imgui-sdl2-support/src/lib.rs +++ b/imgui-sdl2-support/src/lib.rs @@ -15,7 +15,7 @@ use std::time::Instant; -use imgui::{BackendFlags, ConfigFlags, Context, Io, Key, MouseCursor}; +use imgui::{BackendFlags, ConfigFlags, Context, Io, MouseCursor}; use sdl2::{ event::Event, keyboard::{Mod, Scancode}, @@ -348,13 +348,28 @@ impl SdlPlatform { } impl SdlPlatform { - fn handle_mouse_button(&mut self, io: &mut Io, button: &sdl2::mouse::MouseButton, pressed: bool) { + fn handle_mouse_button( + &mut self, + io: &mut Io, + button: &sdl2::mouse::MouseButton, + pressed: bool, + ) { match button { - sdl2::mouse::MouseButton::Left => io.add_mouse_button_event(imgui::MouseButton::Left, pressed), - sdl2::mouse::MouseButton::Right => io.add_mouse_button_event(imgui::MouseButton::Right, pressed), - sdl2::mouse::MouseButton::Middle => io.add_mouse_button_event(imgui::MouseButton::Middle, pressed), - sdl2::mouse::MouseButton::X1 => io.add_mouse_button_event(imgui::MouseButton::Extra1, pressed), - sdl2::mouse::MouseButton::X2 => io.add_mouse_button_event(imgui::MouseButton::Extra2, pressed), + sdl2::mouse::MouseButton::Left => { + io.add_mouse_button_event(imgui::MouseButton::Left, pressed) + } + sdl2::mouse::MouseButton::Right => { + io.add_mouse_button_event(imgui::MouseButton::Right, pressed) + } + sdl2::mouse::MouseButton::Middle => { + io.add_mouse_button_event(imgui::MouseButton::Middle, pressed) + } + sdl2::mouse::MouseButton::X1 => { + io.add_mouse_button_event(imgui::MouseButton::Extra1, pressed) + } + sdl2::mouse::MouseButton::X2 => { + io.add_mouse_button_event(imgui::MouseButton::Extra2, pressed) + } _ => {} } }