Updated winit, glutin and glium dependencies

This commit is contained in:
Robin Quint 2023-11-18 11:29:23 +01:00 committed by Jonathan Spira
parent 8b2722d00b
commit ca05418cb4
18 changed files with 1201 additions and 924 deletions

View File

@ -13,3 +13,6 @@ members = [
package.rust-version = "1.70" package.rust-version = "1.70"
resolver = "2" resolver = "2"
[patch.crates-io]
glium = { git="https://github.com/glium/glium" }

View File

@ -10,7 +10,7 @@ publish = false
[dev-dependencies] [dev-dependencies]
copypasta = "0.8" copypasta = "0.8"
glium = { version = "0.32.1", default-features = true } glium = { version = "0.33.0", default-features = true }
image = "0.23" image = "0.23"
imgui = { path = "../imgui", features = ["tables-api"] } imgui = { path = "../imgui", features = ["tables-api"] }
imgui-glium-renderer = { path = "../imgui-glium-renderer" } imgui-glium-renderer = { path = "../imgui-glium-renderer" }

View File

@ -1,10 +1,11 @@
use glium::glutin; use glium::glutin::surface::WindowSurface;
use glium::glutin::event::{Event, WindowEvent}; use glium::Surface;
use glium::glutin::event_loop::{ControlFlow, EventLoop};
use glium::glutin::window::WindowBuilder;
use glium::{Display, Surface};
use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui};
use imgui_glium_renderer::Renderer; use imgui_glium_renderer::Renderer;
use imgui_winit_support::winit::dpi::LogicalSize;
use imgui_winit_support::winit::event::{Event, WindowEvent};
use imgui_winit_support::winit::event_loop::EventLoop;
use imgui_winit_support::winit::window::{Window, WindowBuilder};
use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_winit_support::{HiDpiMode, WinitPlatform};
use std::path::Path; use std::path::Path;
use std::time::Instant; use std::time::Instant;
@ -13,7 +14,8 @@ mod clipboard;
pub struct System { pub struct System {
pub event_loop: EventLoop<()>, pub event_loop: EventLoop<()>,
pub display: glium::Display, pub window: Window,
pub display: glium::Display<WindowSurface>,
pub imgui: Context, pub imgui: Context,
pub platform: WinitPlatform, pub platform: WinitPlatform,
pub renderer: Renderer, pub renderer: Renderer,
@ -25,13 +27,14 @@ pub fn init(title: &str) -> System {
Some(file_name) => file_name.to_str().unwrap(), Some(file_name) => file_name.to_str().unwrap(),
None => title, None => title,
}; };
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().expect("Failed to create EventLoop");
let context = glutin::ContextBuilder::new().with_vsync(true);
let builder = WindowBuilder::new() let builder = WindowBuilder::new()
.with_title(title.to_owned()) .with_title(title)
.with_inner_size(glutin::dpi::LogicalSize::new(1024f64, 768f64)); .with_inner_size(LogicalSize::new(1024, 768));
let display = let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new()
Display::new(builder, context, &event_loop).expect("Failed to initialize display"); .set_window_builder(builder)
.build(&event_loop);
let mut imgui = Context::create(); let mut imgui = Context::create();
imgui.set_ini_filename(None); imgui.set_ini_filename(None);
@ -44,9 +47,6 @@ pub fn init(title: &str) -> System {
let mut platform = WinitPlatform::init(&mut imgui); let mut platform = WinitPlatform::init(&mut imgui);
{ {
let gl_window = display.gl_window();
let window = gl_window.window();
let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") { let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") {
// Allow forcing of HiDPI factor for debugging purposes // Allow forcing of HiDPI factor for debugging purposes
match factor.parse::<f64>() { match factor.parse::<f64>() {
@ -57,7 +57,7 @@ pub fn init(title: &str) -> System {
HiDpiMode::Default HiDpiMode::Default
}; };
platform.attach_window(imgui.io_mut(), window, dpi_mode); platform.attach_window(imgui.io_mut(), &window, dpi_mode);
} }
// Fixed font size. Note imgui_winit_support uses "logical // Fixed font size. Note imgui_winit_support uses "logical
@ -103,6 +103,7 @@ pub fn init(title: &str) -> System {
System { System {
event_loop, event_loop,
window,
display, display,
imgui, imgui,
platform, platform,
@ -115,6 +116,7 @@ impl System {
pub fn main_loop<F: FnMut(&mut bool, &mut Ui) + 'static>(self, mut run_ui: F) { pub fn main_loop<F: FnMut(&mut bool, &mut Ui) + 'static>(self, mut run_ui: F) {
let System { let System {
event_loop, event_loop,
window,
display, display,
mut imgui, mut imgui,
mut platform, mut platform,
@ -123,46 +125,57 @@ impl System {
} = self; } = self;
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, _, control_flow| match event { event_loop
Event::NewEvents(_) => { .run(move |event, window_target| match event {
let now = Instant::now(); Event::NewEvents(_) => {
imgui.io_mut().update_delta_time(now - last_frame); let now = Instant::now();
last_frame = now; imgui.io_mut().update_delta_time(now - last_frame);
} last_frame = now;
Event::MainEventsCleared => {
let gl_window = display.gl_window();
platform
.prepare_frame(imgui.io_mut(), gl_window.window())
.expect("Failed to prepare frame");
gl_window.window().request_redraw();
}
Event::RedrawRequested(_) => {
let ui = imgui.frame();
let mut run = true;
run_ui(&mut run, ui);
if !run {
*control_flow = ControlFlow::Exit;
} }
Event::AboutToWait => {
platform
.prepare_frame(imgui.io_mut(), &window)
.expect("Failed to prepare frame");
window.request_redraw();
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let ui = imgui.frame();
let gl_window = display.gl_window(); let mut run = true;
let mut target = display.draw(); run_ui(&mut run, ui);
target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); if !run {
platform.prepare_render(ui, gl_window.window()); window_target.exit();
let draw_data = imgui.render(); }
renderer
.render(&mut target, draw_data) let mut target = display.draw();
.expect("Rendering failed"); target.clear_color_srgb(1.0, 1.0, 1.0, 1.0);
target.finish().expect("Failed to swap buffers"); platform.prepare_render(ui, &window);
} let draw_data = imgui.render();
Event::WindowEvent { renderer
event: WindowEvent::CloseRequested, .render(&mut target, draw_data)
.. .expect("Rendering failed");
} => *control_flow = ControlFlow::Exit, target.finish().expect("Failed to swap buffers");
event => { }
let gl_window = display.gl_window(); Event::WindowEvent {
platform.handle_event(imgui.io_mut(), gl_window.window(), &event); event: WindowEvent::Resized(new_size),
} ..
}) } => {
if new_size.width > 0 && new_size.height > 0 {
display.resize((new_size.width, new_size.height));
}
platform.handle_event(imgui.io_mut(), &window, &event);
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => window_target.exit(),
event => {
platform.handle_event(imgui.io_mut(), &window, &event);
}
})
.expect("EventLoop error");
} }
} }

View File

@ -10,8 +10,13 @@ license = "MIT OR Apache-2.0"
categories = ["gui", "rendering"] categories = ["gui", "rendering"]
[dependencies] [dependencies]
glium = { version = "0.32.1", default-features = false } glium = { version = "0.33.0", default-features = false }
imgui = { version = "0.11.0", path = "../imgui" } imgui = { version = "0.11.0", path = "../imgui" }
[dev-dependencies] [dev-dependencies]
glium = { version = "0.33.0", default-features = false, features = ["glutin_backend"] }
imgui-winit-support = {path = "../imgui-winit-support"} imgui-winit-support = {path = "../imgui-winit-support"}
glutin = "0.31.1"
glutin-winit = "0.4.2"
winit = { version = "0.29.3", features = ["rwh_05"] }
raw-window-handle = "0.5.0"

View File

@ -1,6 +1,18 @@
use glium::glutin::event::{Event, WindowEvent}; use std::num::NonZeroU32;
use glium::glutin::event_loop::{ControlFlow, EventLoop};
use glium::Surface; use glium::Surface;
use glutin::{
config::ConfigTemplateBuilder,
context::{ContextAttributesBuilder, NotCurrentGlContext},
display::{GetGlDisplay, GlDisplay},
surface::{SurfaceAttributesBuilder, WindowSurface},
};
use imgui_winit_support::winit::{dpi::LogicalSize, event_loop::EventLoop, window::WindowBuilder};
use raw_window_handle::HasRawWindowHandle;
use winit::{
event::{Event, WindowEvent},
window::Window,
};
const TITLE: &str = "Hello, imgui-rs!"; const TITLE: &str = "Hello, imgui-rs!";
@ -8,8 +20,8 @@ fn main() {
// Common setup for creating a winit window and imgui context, not specifc // Common setup for creating a winit window and imgui context, not specifc
// to this renderer at all except that glutin is used to create the window // to this renderer at all except that glutin is used to create the window
// since it will give us access to a GL context // since it will give us access to a GL context
let (event_loop, display) = create_window(); let (event_loop, window, display) = create_window();
let (mut winit_platform, mut imgui_context) = imgui_init(&display); let (mut winit_platform, mut imgui_context) = imgui_init(&window);
// Create renderer from this crate // Create renderer from this crate
let mut renderer = imgui_glium_renderer::Renderer::init(&mut imgui_context, &display) let mut renderer = imgui_glium_renderer::Renderer::init(&mut imgui_context, &display)
@ -19,73 +31,112 @@ fn main() {
let mut last_frame = std::time::Instant::now(); let mut last_frame = std::time::Instant::now();
// Standard winit event loop // Standard winit event loop
event_loop.run(move |event, _, control_flow| match event { event_loop
Event::NewEvents(_) => { .run(move |event, window_target| match event {
let now = std::time::Instant::now(); Event::NewEvents(_) => {
imgui_context.io_mut().update_delta_time(now - last_frame); let now = std::time::Instant::now();
last_frame = now; imgui_context.io_mut().update_delta_time(now - last_frame);
} last_frame = now;
Event::MainEventsCleared => { }
let gl_window = display.gl_window(); Event::AboutToWait => {
winit_platform winit_platform
.prepare_frame(imgui_context.io_mut(), gl_window.window()) .prepare_frame(imgui_context.io_mut(), &window)
.expect("Failed to prepare frame"); .expect("Failed to prepare frame");
gl_window.window().request_redraw(); window.request_redraw();
} }
Event::RedrawRequested(_) => { Event::WindowEvent {
// Create frame for the all important `&imgui::Ui` event: WindowEvent::RedrawRequested,
let ui = imgui_context.frame(); ..
} => {
// Create frame for the all important `&imgui::Ui`
let ui = imgui_context.frame();
// Draw our example content // Draw our example content
ui.show_demo_window(&mut true); ui.show_demo_window(&mut true);
// Setup for drawing // Setup for drawing
let gl_window = display.gl_window(); let mut target = display.draw();
let mut target = display.draw();
// Renderer doesn't automatically clear window // Renderer doesn't automatically clear window
target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); target.clear_color_srgb(1.0, 1.0, 1.0, 1.0);
// Perform rendering // Perform rendering
winit_platform.prepare_render(ui, gl_window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
renderer renderer
.render(&mut target, draw_data) .render(&mut target, draw_data)
.expect("Rendering failed"); .expect("Rendering failed");
target.finish().expect("Failed to swap buffers"); target.finish().expect("Failed to swap buffers");
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = ControlFlow::Exit, } => window_target.exit(),
event => { winit::event::Event::WindowEvent {
let gl_window = display.gl_window(); event: winit::event::WindowEvent::Resized(new_size),
winit_platform.handle_event(imgui_context.io_mut(), gl_window.window(), &event); ..
} } => {
}); if new_size.width > 0 && new_size.height > 0 {
display.resize((new_size.width, new_size.height));
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
})
.expect("EventLoop error");
} }
fn create_window() -> (EventLoop<()>, glium::Display) { fn create_window() -> (EventLoop<()>, Window, glium::Display<WindowSurface>) {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().expect("Failed to create EventLoop");
let context = glium::glutin::ContextBuilder::new().with_vsync(true);
let builder = glium::glutin::window::WindowBuilder::new()
.with_title(TITLE.to_owned())
.with_inner_size(glium::glutin::dpi::LogicalSize::new(1024f64, 768f64));
let display =
glium::Display::new(builder, context, &event_loop).expect("Failed to initialize display");
(event_loop, display) let window_builder = WindowBuilder::new()
.with_title(TITLE)
.with_inner_size(LogicalSize::new(1024, 768));
let (window, cfg) = glutin_winit::DisplayBuilder::new()
.with_window_builder(Some(window_builder))
.build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| {
configs.next().unwrap()
})
.expect("Failed to create OpenGL window");
let window = window.unwrap();
let context_attribs = ContextAttributesBuilder::new().build(Some(window.raw_window_handle()));
let context = unsafe {
cfg.display()
.create_context(&cfg, &context_attribs)
.expect("Failed to create OpenGL context")
};
let surface_attribs = SurfaceAttributesBuilder::<WindowSurface>::new().build(
window.raw_window_handle(),
NonZeroU32::new(1024).unwrap(),
NonZeroU32::new(768).unwrap(),
);
let surface = unsafe {
cfg.display()
.create_window_surface(&cfg, &surface_attribs)
.expect("Failed to create OpenGL surface")
};
let context = context
.make_current(&surface)
.expect("Failed to make OpenGL context current");
let display = glium::Display::from_context_surface(context, surface)
.expect("Failed to create glium Display");
(event_loop, window, display)
} }
fn imgui_init(display: &glium::Display) -> (imgui_winit_support::WinitPlatform, imgui::Context) { fn imgui_init(window: &Window) -> (imgui_winit_support::WinitPlatform, imgui::Context) {
let mut imgui_context = imgui::Context::create(); let mut imgui_context = imgui::Context::create();
imgui_context.set_ini_filename(None); imgui_context.set_ini_filename(None);
let mut winit_platform = imgui_winit_support::WinitPlatform::init(&mut imgui_context); let mut winit_platform = imgui_winit_support::WinitPlatform::init(&mut imgui_context);
let gl_window = display.gl_window();
let window = gl_window.window();
let dpi_mode = imgui_winit_support::HiDpiMode::Default; let dpi_mode = imgui_winit_support::HiDpiMode::Default;
winit_platform.attach_window(imgui_context.io_mut(), window, dpi_mode); winit_platform.attach_window(imgui_context.io_mut(), window, dpi_mode);

View File

@ -113,7 +113,7 @@ impl glium::vertex::Vertex for GliumDrawVert {
#[inline] #[inline]
fn build_bindings() -> glium::vertex::VertexFormat { fn build_bindings() -> glium::vertex::VertexFormat {
use std::borrow::Cow::*; use std::borrow::Cow::*;
Borrowed(&[ &[
( (
Borrowed("pos"), Borrowed("pos"),
0, 0,
@ -135,7 +135,7 @@ impl glium::vertex::Vertex for GliumDrawVert {
glium::vertex::AttributeType::U8U8U8U8, glium::vertex::AttributeType::U8U8U8U8,
false, false,
), ),
]) ]
} }
} }

View File

@ -14,9 +14,12 @@ glow = "0.12.0"
memoffset = "0.9" memoffset = "0.9"
[dev-dependencies] [dev-dependencies]
glutin = "0.29.1" glutin = "0.31.1"
glutin-winit = "0.4.2"
imgui-winit-support = { version = "0.11.0", path = "../imgui-winit-support" } imgui-winit-support = { version = "0.11.0", path = "../imgui-winit-support" }
image = "0.23" image = "0.23"
raw-window-handle = "0.5.0"
winit = { version = "0.29.3", features = ["rwh_05"] }
[features] [features]
# Features here are used to opt-out of compiling code that depends on certain # Features here are used to opt-out of compiling code that depends on certain

View File

@ -1,25 +1,36 @@
//! A basic self-contained example to get you from zero-to-demo-window as fast //! A basic self-contained example to get you from zero-to-demo-window as fast
//! as possible. //! as possible.
use std::time::Instant; use std::{num::NonZeroU32, time::Instant};
use glow::HasContext; use glow::HasContext;
use glutin::{event_loop::EventLoop, WindowedContext}; use glutin::{
use imgui_winit_support::WinitPlatform; config::ConfigTemplateBuilder,
context::{ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext},
display::{GetGlDisplay, GlDisplay},
surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface},
};
use imgui_winit_support::{
winit::{
dpi::LogicalSize,
event_loop::EventLoop,
window::{Window, WindowBuilder},
},
WinitPlatform,
};
use raw_window_handle::HasRawWindowHandle;
const TITLE: &str = "Hello, imgui-rs!"; const TITLE: &str = "Hello, imgui-rs!";
type Window = WindowedContext<glutin::PossiblyCurrent>;
fn main() { fn main() {
// Common setup for creating a winit window and imgui context, not specifc // Common setup for creating a winit window and imgui context, not specifc
// to this renderer at all except that glutin is used to create the window // to this renderer at all except that glutin is used to create the window
// since it will give us access to a GL context // since it will give us access to a GL context
let (event_loop, window) = create_window(); let (event_loop, window, surface, context) = create_window();
let (mut winit_platform, mut imgui_context) = imgui_init(&window); let (mut winit_platform, mut imgui_context) = imgui_init(&window);
// OpenGL context from glow // OpenGL context from glow
let gl = glow_context(&window); let gl = glow_context(&context);
// OpenGL renderer from this crate // OpenGL renderer from this crate
let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context)
@ -28,70 +39,122 @@ fn main() {
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
// Standard winit event loop // Standard winit event loop
event_loop.run(move |event, _, control_flow| { event_loop
match event { .run(move |event, window_target| {
glutin::event::Event::NewEvents(_) => { match event {
let now = Instant::now(); winit::event::Event::NewEvents(_) => {
imgui_context let now = Instant::now();
.io_mut() imgui_context
.update_delta_time(now.duration_since(last_frame)); .io_mut()
last_frame = now; .update_delta_time(now.duration_since(last_frame));
} last_frame = now;
glutin::event::Event::MainEventsCleared => { }
winit_platform winit::event::Event::AboutToWait => {
.prepare_frame(imgui_context.io_mut(), window.window()) winit_platform
.unwrap(); .prepare_frame(imgui_context.io_mut(), &window)
window.window().request_redraw(); .unwrap();
} window.request_redraw();
glutin::event::Event::RedrawRequested(_) => { }
// The renderer assumes you'll be clearing the buffer yourself winit::event::Event::WindowEvent {
unsafe { ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) }; event: winit::event::WindowEvent::RedrawRequested,
..
} => {
// The renderer assumes you'll be clearing the buffer yourself
unsafe { ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) };
let ui = imgui_context.frame(); let ui = imgui_context.frame();
ui.show_demo_window(&mut true); ui.show_demo_window(&mut true);
winit_platform.prepare_render(ui, window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
// This is the only extra render step to add // This is the only extra render step to add
ig_renderer ig_renderer
.render(draw_data) .render(draw_data)
.expect("error rendering imgui"); .expect("error rendering imgui");
window.swap_buffers().unwrap(); surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
window_target.exit();
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0 && new_size.height > 0 {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
} }
glutin::event::Event::WindowEvent { })
event: glutin::event::WindowEvent::CloseRequested, .expect("EventLoop error");
..
} => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
}
}
});
} }
fn create_window() -> (EventLoop<()>, Window) { fn create_window() -> (
let event_loop = glutin::event_loop::EventLoop::new(); EventLoop<()>,
let window = glutin::window::WindowBuilder::new() Window,
Surface<WindowSurface>,
PossiblyCurrentContext,
) {
let event_loop = EventLoop::new().unwrap();
let window_builder = WindowBuilder::new()
.with_title(TITLE) .with_title(TITLE)
.with_inner_size(glutin::dpi::LogicalSize::new(1024, 768)); .with_inner_size(LogicalSize::new(1024, 768));
let window = glutin::ContextBuilder::new() let (window, cfg) = glutin_winit::DisplayBuilder::new()
.with_vsync(true) .with_window_builder(Some(window_builder))
.build_windowed(window, &event_loop) .build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| {
.expect("could not create window"); configs.next().unwrap()
let window = unsafe { })
window .expect("Failed to create OpenGL window");
.make_current()
.expect("could not make window context current") let window = window.unwrap();
let context_attribs = ContextAttributesBuilder::new().build(Some(window.raw_window_handle()));
let context = unsafe {
cfg.display()
.create_context(&cfg, &context_attribs)
.expect("Failed to create OpenGL context")
}; };
(event_loop, window)
let surface_attribs = SurfaceAttributesBuilder::<WindowSurface>::new()
.with_srgb(Some(true))
.build(
window.raw_window_handle(),
NonZeroU32::new(1024).unwrap(),
NonZeroU32::new(768).unwrap(),
);
let surface = unsafe {
cfg.display()
.create_window_surface(&cfg, &surface_attribs)
.expect("Failed to create OpenGL surface")
};
let context = context
.make_current(&surface)
.expect("Failed to make OpenGL context current");
(event_loop, window, surface, context)
} }
fn glow_context(window: &Window) -> glow::Context { fn glow_context(context: &PossiblyCurrentContext) -> glow::Context {
unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) } unsafe {
glow::Context::from_loader_function_cstr(|s| context.display().get_proc_address(s).cast())
}
} }
fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
@ -101,7 +164,7 @@ fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
let mut winit_platform = WinitPlatform::init(&mut imgui_context); let mut winit_platform = WinitPlatform::init(&mut imgui_context);
winit_platform.attach_window( winit_platform.attach_window(
imgui_context.io_mut(), imgui_context.io_mut(),
window.window(), window,
imgui_winit_support::HiDpiMode::Rounded, imgui_winit_support::HiDpiMode::Rounded,
); );

View File

@ -1,68 +1,89 @@
//! A basic example showing imgui rendering on top of a simple custom scene. //! A basic example showing imgui rendering on top of a simple custom scene.
use std::time::Instant; use std::{num::NonZeroU32, time::Instant};
mod utils; mod utils;
use glutin::surface::GlSurface;
use utils::Triangler; use utils::Triangler;
fn main() { fn main() {
let (event_loop, window) = utils::create_window("Hello, triangle!", glutin::GlRequest::Latest); let (event_loop, window, surface, context) = utils::create_window("Hello, triangle!", None);
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
let gl = utils::glow_context(&window); let gl = utils::glow_context(&context);
let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context)
.expect("failed to create renderer"); .expect("failed to create renderer");
let tri_renderer = Triangler::new(ig_renderer.gl_context(), "#version 330"); let tri_renderer = Triangler::new(ig_renderer.gl_context(), "#version 330");
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, _, control_flow| { event_loop
match event { .run(move |event, window_target| {
glutin::event::Event::NewEvents(_) => { match event {
let now = Instant::now(); winit::event::Event::NewEvents(_) => {
imgui_context let now = Instant::now();
.io_mut() imgui_context
.update_delta_time(now.duration_since(last_frame)); .io_mut()
last_frame = now; .update_delta_time(now.duration_since(last_frame));
} last_frame = now;
glutin::event::Event::MainEventsCleared => { }
winit_platform winit::event::Event::AboutToWait => {
.prepare_frame(imgui_context.io_mut(), window.window()) winit_platform
.unwrap(); .prepare_frame(imgui_context.io_mut(), &window)
.unwrap();
window.window().request_redraw(); window.request_redraw();
} }
glutin::event::Event::RedrawRequested(_) => { winit::event::Event::WindowEvent {
// Render your custom scene, note we need to borrow the OpenGL event: winit::event::WindowEvent::RedrawRequested,
// context from the `AutoRenderer`, which takes ownership of it. ..
tri_renderer.render(ig_renderer.gl_context()); } => {
// Render your custom scene, note we need to borrow the OpenGL
// context from the `AutoRenderer`, which takes ownership of it.
tri_renderer.render(ig_renderer.gl_context());
let ui = imgui_context.frame(); let ui = imgui_context.frame();
ui.show_demo_window(&mut true); ui.show_demo_window(&mut true);
winit_platform.prepare_render(ui, window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
// Render imgui on top of it // Render imgui on top of it
ig_renderer ig_renderer
.render(draw_data) .render(draw_data)
.expect("error rendering imgui"); .expect("error rendering imgui");
window.swap_buffers().unwrap(); surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
window_target.exit();
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0 && new_size.height > 0 {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
winit::event::Event::LoopExiting => {
let gl = ig_renderer.gl_context();
tri_renderer.destroy(gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
} }
glutin::event::Event::WindowEvent { })
event: glutin::event::WindowEvent::CloseRequested, .expect("EventLoop error");
..
} => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
glutin::event::Event::LoopDestroyed => {
let gl = ig_renderer.gl_context();
tri_renderer.destroy(gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
}
}
});
} }

View File

@ -4,19 +4,23 @@
//! Note this example uses `Renderer` rather than `AutoRenderer` and //! Note this example uses `Renderer` rather than `AutoRenderer` and
//! therefore requries more lifetime-management of the OpenGL context. //! therefore requries more lifetime-management of the OpenGL context.
use std::time::Instant; use std::{num::NonZeroU32, time::Instant};
mod utils; mod utils;
use glutin::{
context::{ContextApi, Version},
surface::GlSurface,
};
use utils::Triangler; use utils::Triangler;
fn main() { fn main() {
let (event_loop, window) = utils::create_window( let (event_loop, window, surface, context) = utils::create_window(
"Hello, triangle! (GLES 3.0)", "Hello, triangle! (GLES 3.0)",
glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)), Some(ContextApi::Gles(Some(Version::new(3, 0)))),
); );
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
let gl = utils::glow_context(&window); let gl = utils::glow_context(&context);
// When using `Renderer`, we need to create a texture map // When using `Renderer`, we need to create a texture map
let mut texture_map = imgui_glow_renderer::SimpleTextureMap::default(); let mut texture_map = imgui_glow_renderer::SimpleTextureMap::default();
@ -31,54 +35,74 @@ fn main() {
let tri_renderer = Triangler::new(&gl, "#version 300 es\nprecision mediump float;"); let tri_renderer = Triangler::new(&gl, "#version 300 es\nprecision mediump float;");
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, _, control_flow| { event_loop
match event { .run(move |event, window_target| {
glutin::event::Event::NewEvents(_) => { match event {
let now = Instant::now(); winit::event::Event::NewEvents(_) => {
imgui_context let now = Instant::now();
.io_mut() imgui_context
.update_delta_time(now.duration_since(last_frame)); .io_mut()
last_frame = now; .update_delta_time(now.duration_since(last_frame));
} last_frame = now;
glutin::event::Event::MainEventsCleared => { }
winit_platform winit::event::Event::AboutToWait => {
.prepare_frame(imgui_context.io_mut(), window.window()) winit_platform
.unwrap(); .prepare_frame(imgui_context.io_mut(), &window)
.unwrap();
window.window().request_redraw(); window.request_redraw();
} }
glutin::event::Event::RedrawRequested(_) => { winit::event::Event::WindowEvent {
// Draw custom scene event: winit::event::WindowEvent::RedrawRequested,
tri_renderer.render(&gl); ..
} => {
// Draw custom scene
tri_renderer.render(&gl);
let ui = imgui_context.frame(); let ui = imgui_context.frame();
ui.show_demo_window(&mut true); ui.show_demo_window(&mut true);
winit_platform.prepare_render(ui, window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
// Render imgui on top // Render imgui on top
ig_renderer ig_renderer
.render(&gl, &texture_map, draw_data) .render(&gl, &texture_map, draw_data)
.expect("error rendering imgui"); .expect("error rendering imgui");
window.swap_buffers().unwrap(); surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
window_target.exit();
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0 && new_size.height > 0 {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
winit::event::Event::LoopExiting => {
tri_renderer.destroy(&gl);
// Note, to be good citizens we should manually call destroy
// when the renderer does not own the GL context
ig_renderer.destroy(&gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
} }
glutin::event::Event::WindowEvent { })
event: glutin::event::WindowEvent::CloseRequested, .expect("EventLoop error");
..
} => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
glutin::event::Event::LoopDestroyed => {
tri_renderer.destroy(&gl);
// Note, to be good citizens we should manually call destroy
// when the renderer does not own the GL context
ig_renderer.destroy(&gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
}
}
});
} }

View File

@ -5,13 +5,15 @@
//! OpenGL automatically converts colors to linear space before the shaders. //! OpenGL automatically converts colors to linear space before the shaders.
//! The renderer assumes you set this internal format correctly like this. //! The renderer assumes you set this internal format correctly like this.
use std::{io::Cursor, time::Instant}; use std::{io::Cursor, num::NonZeroU32, time::Instant};
use glow::HasContext; use glow::HasContext;
use glutin::surface::GlSurface;
use image::{jpeg::JpegDecoder, ImageDecoder}; use image::{jpeg::JpegDecoder, ImageDecoder};
use imgui::Condition; use imgui::Condition;
use imgui_glow_renderer::Renderer; use imgui_glow_renderer::Renderer;
use winit::event_loop::ControlFlow;
#[allow(dead_code)] #[allow(dead_code)]
mod utils; mod utils;
@ -19,9 +21,9 @@ mod utils;
const LENNA_JPEG: &[u8] = include_bytes!("../../resources/Lenna.jpg"); const LENNA_JPEG: &[u8] = include_bytes!("../../resources/Lenna.jpg");
fn main() { fn main() {
let (event_loop, window) = utils::create_window("Custom textures", glutin::GlRequest::Latest); let (event_loop, window, surface, context) = utils::create_window("Custom textures", None);
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
let gl = utils::glow_context(&window); let gl = utils::glow_context(&context);
// This time, we tell OpenGL this is an sRGB framebuffer and OpenGL will // This time, we tell OpenGL this is an sRGB framebuffer and OpenGL will
// do the conversion to sSGB space for us after the fragment shader. // do the conversion to sSGB space for us after the fragment shader.
unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) }; unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
@ -35,55 +37,75 @@ fn main() {
let textures_ui = TexturesUi::new(&gl, &mut textures); let textures_ui = TexturesUi::new(&gl, &mut textures);
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, _, control_flow| { event_loop
// Note we can potentially make the loop more efficient by .run(move |event, window_target| {
// changing the `Poll` (default) value to `ControlFlow::Wait` // Note we can potentially make the loop more efficient by
// but be careful to test on all target platforms! // changing the `Poll` (default) value to `ControlFlow::Wait`
*control_flow = glutin::event_loop::ControlFlow::Poll; // but be careful to test on all target platforms!
window_target.set_control_flow(ControlFlow::Poll);
match event { match event {
glutin::event::Event::NewEvents(_) => { winit::event::Event::NewEvents(_) => {
let now = Instant::now(); let now = Instant::now();
imgui_context imgui_context
.io_mut() .io_mut()
.update_delta_time(now.duration_since(last_frame)); .update_delta_time(now.duration_since(last_frame));
last_frame = now; last_frame = now;
} }
glutin::event::Event::MainEventsCleared => { winit::event::Event::AboutToWait => {
winit_platform winit_platform
.prepare_frame(imgui_context.io_mut(), window.window()) .prepare_frame(imgui_context.io_mut(), &window)
.unwrap(); .unwrap();
window.window().request_redraw(); window.request_redraw();
} }
glutin::event::Event::RedrawRequested(_) => { winit::event::Event::WindowEvent {
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }; event: winit::event::WindowEvent::RedrawRequested,
..
} => {
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) };
let ui = imgui_context.frame(); let ui = imgui_context.frame();
textures_ui.show(ui); textures_ui.show(ui);
winit_platform.prepare_render(ui, window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
ig_renderer ig_renderer
.render(&gl, &textures, draw_data) .render(&gl, &textures, draw_data)
.expect("error rendering imgui"); .expect("error rendering imgui");
window.swap_buffers().unwrap(); surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0 && new_size.height > 0 {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
window_target.exit();
}
winit::event::Event::LoopExiting => {
ig_renderer.destroy(&gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
} }
glutin::event::Event::WindowEvent { })
event: glutin::event::WindowEvent::CloseRequested, .expect("EventLoop error");
..
} => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
glutin::event::Event::LoopDestroyed => {
ig_renderer.destroy(&gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
}
}
});
} }
struct TexturesUi { struct TexturesUi {

View File

@ -1,10 +1,11 @@
//! A basic example showing imgui rendering on top of a simple custom scene. //! A basic example showing imgui rendering on top of a simple custom scene.
use std::{cell::RefCell, rc::Rc, time::Instant}; use std::{cell::RefCell, num::NonZeroU32, rc::Rc, time::Instant};
mod utils; mod utils;
use glow::HasContext; use glow::HasContext;
use glutin::surface::GlSurface;
use utils::Triangler; use utils::Triangler;
struct UserData { struct UserData {
@ -16,9 +17,9 @@ struct UserData {
const FBO_SIZE: i32 = 128; const FBO_SIZE: i32 = 128;
fn main() { fn main() {
let (event_loop, window) = utils::create_window("Hello, FBO!", glutin::GlRequest::Latest); let (event_loop, window, surface, context) = utils::create_window("Hello, FBO!", None);
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
let gl = utils::glow_context(&window); let gl = utils::glow_context(&context);
let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context)
.expect("failed to create renderer"); .expect("failed to create renderer");
@ -55,96 +56,124 @@ fn main() {
})); }));
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, _, control_flow| { event_loop
match event { .run(move |event, window_target| {
glutin::event::Event::NewEvents(_) => { match event {
let now = Instant::now(); winit::event::Event::NewEvents(_) => {
imgui_context let now = Instant::now();
.io_mut() imgui_context
.update_delta_time(now.duration_since(last_frame)); .io_mut()
last_frame = now; .update_delta_time(now.duration_since(last_frame));
} last_frame = now;
glutin::event::Event::MainEventsCleared => {
winit_platform
.prepare_frame(imgui_context.io_mut(), window.window())
.unwrap();
window.window().request_redraw();
}
glutin::event::Event::RedrawRequested(_) => {
// Render your custom scene, note we need to borrow the OpenGL
// context from the `AutoRenderer`, which takes ownership of it.
unsafe {
ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT);
} }
winit::event::Event::AboutToWait => {
winit_platform
.prepare_frame(imgui_context.io_mut(), &window)
.unwrap();
let ui = imgui_context.frame(); window.request_redraw();
ui.show_demo_window(&mut true); }
ui.window("FBO").resizable(false).build(|| { winit::event::Event::WindowEvent {
let pos = ui.cursor_screen_pos(); event: winit::event::WindowEvent::RedrawRequested,
ui.set_cursor_screen_pos([pos[0] + FBO_SIZE as f32, pos[1] + FBO_SIZE as f32]); ..
} => {
// Render your custom scene, note we need to borrow the OpenGL
// context from the `AutoRenderer`, which takes ownership of it.
unsafe {
ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT);
}
let draws = ui.get_window_draw_list(); let ui = imgui_context.frame();
let scale = ui.io().display_framebuffer_scale; ui.show_demo_window(&mut true);
let dsp_size = ui.io().display_size; ui.window("FBO").resizable(false).build(|| {
draws let pos = ui.cursor_screen_pos();
.add_callback({ ui.set_cursor_screen_pos([
let data = Rc::clone(&data); pos[0] + FBO_SIZE as f32,
move || { pos[1] + FBO_SIZE as f32,
let data = data.borrow(); ]);
let gl = &*data.gl;
unsafe { let draws = ui.get_window_draw_list();
let x = pos[0] * scale[0]; let scale = ui.io().display_framebuffer_scale;
let y = (dsp_size[1] - pos[1]) * scale[1]; let dsp_size = ui.io().display_size;
let dst_x0 = x as i32; draws
let dst_y0 = (y - FBO_SIZE as f32 * scale[1]) as i32; .add_callback({
let dst_x1 = (x + FBO_SIZE as f32 * scale[0]) as i32; let data = Rc::clone(&data);
let dst_y1 = y as i32; move || {
gl.scissor(dst_x0, dst_y0, dst_x1 - dst_x0, dst_y1 - dst_y0); let data = data.borrow();
gl.enable(glow::SCISSOR_TEST); let gl = &*data.gl;
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(data.fbo)); unsafe {
gl.blit_framebuffer( let x = pos[0] * scale[0];
0, let y = (dsp_size[1] - pos[1]) * scale[1];
0, let dst_x0 = x as i32;
FBO_SIZE, let dst_y0 = (y - FBO_SIZE as f32 * scale[1]) as i32;
FBO_SIZE, let dst_x1 = (x + FBO_SIZE as f32 * scale[0]) as i32;
dst_x0, let dst_y1 = y as i32;
dst_y0, gl.scissor(
dst_x1, dst_x0,
dst_y1, dst_y0,
glow::COLOR_BUFFER_BIT, dst_x1 - dst_x0,
glow::NEAREST, dst_y1 - dst_y0,
); );
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None); gl.enable(glow::SCISSOR_TEST);
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(data.fbo));
gl.blit_framebuffer(
0,
0,
FBO_SIZE,
FBO_SIZE,
dst_x0,
dst_y0,
dst_x1,
dst_y1,
glow::COLOR_BUFFER_BIT,
glow::NEAREST,
);
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None);
}
} }
} })
}) .build();
.build(); });
});
winit_platform.prepare_render(ui, window.window()); winit_platform.prepare_render(ui, &window);
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
// Render imgui on top of it // Render imgui on top of it
ig_renderer ig_renderer
.render(draw_data) .render(draw_data)
.expect("error rendering imgui"); .expect("error rendering imgui");
window.swap_buffers().unwrap(); surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
window_target.exit();
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(new_size),
..
} => {
if new_size.width > 0 && new_size.height > 0 {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
winit::event::Event::LoopExiting => {
let gl = ig_renderer.gl_context();
tri_renderer.destroy(gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
}
} }
glutin::event::Event::WindowEvent { })
event: glutin::event::WindowEvent::CloseRequested, .expect("EventLoop error");
..
} => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
glutin::event::Event::LoopDestroyed => {
let gl = ig_renderer.gl_context();
tri_renderer.destroy(gl);
}
event => {
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
}
}
});
} }

View File

@ -1,29 +1,82 @@
use std::num::NonZeroU32;
use glow::HasContext; use glow::HasContext;
use glutin::{event_loop::EventLoop, GlRequest}; use glutin::{
config::ConfigTemplateBuilder,
context::{ContextApi, ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext},
display::{GetGlDisplay, GlDisplay},
surface::{GlSurface, Surface, SurfaceAttributesBuilder, SwapInterval, WindowSurface},
};
use imgui_winit_support::WinitPlatform; use imgui_winit_support::WinitPlatform;
use raw_window_handle::HasRawWindowHandle;
use winit::{
dpi::LogicalSize,
event_loop::EventLoop,
window::{Window, WindowBuilder},
};
pub type Window = glutin::WindowedContext<glutin::PossiblyCurrent>; pub fn create_window(
title: &str,
context_api: Option<ContextApi>,
) -> (
EventLoop<()>,
Window,
Surface<WindowSurface>,
PossiblyCurrentContext,
) {
let event_loop = EventLoop::new().unwrap();
pub fn create_window(title: &str, gl_request: GlRequest) -> (EventLoop<()>, Window) { let window_builder = WindowBuilder::new()
let event_loop = glutin::event_loop::EventLoop::new();
let window = glutin::window::WindowBuilder::new()
.with_title(title) .with_title(title)
.with_inner_size(glutin::dpi::LogicalSize::new(1024, 768)); .with_inner_size(LogicalSize::new(1024, 768));
let window = glutin::ContextBuilder::new() let (window, cfg) = glutin_winit::DisplayBuilder::new()
.with_gl(gl_request) .with_window_builder(Some(window_builder))
.with_vsync(true) .build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| {
.build_windowed(window, &event_loop) configs.next().unwrap()
.expect("could not create window"); })
let window = unsafe { .expect("Failed to create OpenGL window");
window
.make_current() let window = window.unwrap();
.expect("could not make window context current")
let mut context_attribs = ContextAttributesBuilder::new();
if let Some(context_api) = context_api {
context_attribs = context_attribs.with_context_api(context_api);
}
let context_attribs = context_attribs.build(Some(window.raw_window_handle()));
let context = unsafe {
cfg.display()
.create_context(&cfg, &context_attribs)
.expect("Failed to create OpenGL context")
}; };
(event_loop, window)
let surface_attribs = SurfaceAttributesBuilder::<WindowSurface>::new()
.with_srgb(Some(true))
.build(
window.raw_window_handle(),
NonZeroU32::new(1024).unwrap(),
NonZeroU32::new(768).unwrap(),
);
let surface = unsafe {
cfg.display()
.create_window_surface(&cfg, &surface_attribs)
.expect("Failed to create OpenGL surface")
};
let context = context
.make_current(&surface)
.expect("Failed to make OpenGL context current");
surface
.set_swap_interval(&context, SwapInterval::Wait(NonZeroU32::new(1).unwrap()))
.expect("Failed to set swap interval");
(event_loop, window, surface, context)
} }
pub fn glow_context(window: &Window) -> glow::Context { pub fn glow_context(context: &PossiblyCurrentContext) -> glow::Context {
unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) } unsafe {
glow::Context::from_loader_function_cstr(|s| context.display().get_proc_address(s).cast())
}
} }
pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
@ -33,7 +86,7 @@ pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
let mut winit_platform = WinitPlatform::init(&mut imgui_context); let mut winit_platform = WinitPlatform::init(&mut imgui_context);
winit_platform.attach_window( winit_platform.attach_window(
imgui_context.io_mut(), imgui_context.io_mut(),
window.window(), window,
imgui_winit_support::HiDpiMode::Rounded, imgui_winit_support::HiDpiMode::Rounded,
); );

View File

@ -13,8 +13,8 @@ license = "MIT OR Apache-2.0"
imgui = { version = "0.11.0", path="../imgui", features=["docking"] } imgui = { version = "0.11.0", path="../imgui", features=["docking"] }
glow = "0.12.0" glow = "0.12.0"
glutin = "0.30.3" glutin = "0.31.1"
glutin-winit = "0.4.2"
raw-window-handle = "0.5.0" raw-window-handle = "0.5.0"
winit = "0.27.5" winit = "0.29.3"
thiserror = "1.0.38" thiserror = "1.0.38"
glutin-winit = "0.2.1"

View File

@ -3,21 +3,24 @@ use std::{ffi::CString, num::NonZeroU32, time::Instant};
use glow::{Context, HasContext}; use glow::{Context, HasContext};
use glutin::{ use glutin::{
config::ConfigTemplateBuilder, config::ConfigTemplateBuilder,
context::ContextAttributesBuilder, context::{ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentGlContext},
display::GetGlDisplay, display::GetGlDisplay,
prelude::{ prelude::GlDisplay,
GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentContextGlSurfaceAccessor,
},
surface::{GlSurface, SurfaceAttributesBuilder, WindowSurface}, surface::{GlSurface, SurfaceAttributesBuilder, WindowSurface},
}; };
use glutin_winit::DisplayBuilder; use glutin_winit::DisplayBuilder;
use imgui::ConfigFlags; use imgui::ConfigFlags;
use imgui_winit_glow_renderer_viewports::Renderer; use imgui_winit_glow_renderer_viewports::Renderer;
use raw_window_handle::HasRawWindowHandle; use raw_window_handle::HasRawWindowHandle;
use winit::{dpi::LogicalSize, event::WindowEvent, event_loop::EventLoop, window::WindowBuilder}; use winit::{
dpi::LogicalSize,
event::WindowEvent,
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() { fn main() {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().expect("Failed to create EventLoop");
let window_builder = WindowBuilder::new() let window_builder = WindowBuilder::new()
.with_inner_size(LogicalSize::new(800.0, 600.0)) .with_inner_size(LogicalSize::new(800.0, 600.0))
@ -82,81 +85,86 @@ fn main() {
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
event_loop.run(move |event, window_target, control_flow| { event_loop
control_flow.set_poll(); .run(move |event, window_target| {
window_target.set_control_flow(ControlFlow::Poll);
renderer.handle_event(&mut imgui, &window, &event); renderer.handle_event(&mut imgui, &window, &event);
match event { match event {
winit::event::Event::NewEvents(_) => { winit::event::Event::NewEvents(_) => {
let now = Instant::now(); let now = Instant::now();
imgui.io_mut().update_delta_time(now - last_frame); imgui.io_mut().update_delta_time(now - last_frame);
last_frame = now; last_frame = now;
}
winit::event::Event::WindowEvent {
window_id,
event: WindowEvent::CloseRequested,
} if window_id == window.id() => {
control_flow.set_exit();
}
winit::event::Event::WindowEvent {
window_id,
event: WindowEvent::Resized(new_size),
} if window_id == window.id() => {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit::event::Event::MainEventsCleared => {
window.request_redraw();
}
winit::event::Event::RedrawRequested(_) => {
let ui = imgui.frame();
ui.dockspace_over_main_viewport();
ui.show_demo_window(&mut true);
ui.window("Style Editor").build(|| {
ui.show_default_style_editor();
});
ui.end_frame_early();
renderer.prepare_render(&mut imgui, &window);
imgui.update_platform_windows();
renderer
.update_viewports(&mut imgui, window_target, &glow)
.expect("Failed to update viewports");
let draw_data = imgui.render();
if let Err(e) = context.make_current(&surface) {
// For some reason make_current randomly throws errors on windows.
// Until the reason for this is found, we just print it out instead of panicing.
eprintln!("Failed to make current: {e}");
} }
winit::event::Event::WindowEvent {
unsafe { window_id,
glow.disable(glow::SCISSOR_TEST); event: WindowEvent::CloseRequested,
glow.clear(glow::COLOR_BUFFER_BIT); } if window_id == window.id() => {
window_target.exit();
} }
winit::event::Event::WindowEvent {
window_id,
event: WindowEvent::Resized(new_size),
} if window_id == window.id() => {
surface.resize(
&context,
NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(),
);
}
winit::event::Event::AboutToWait => {
window.request_redraw();
}
winit::event::Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let ui = imgui.frame();
renderer ui.dockspace_over_main_viewport();
.render(&window, &glow, draw_data)
.expect("Failed to render main viewport");
surface ui.show_demo_window(&mut true);
.swap_buffers(&context) ui.window("Style Editor").build(|| {
.expect("Failed to swap buffers"); ui.show_default_style_editor();
});
renderer ui.end_frame_early();
.render_viewports(&glow, &mut imgui)
.expect("Failed to render viewports"); renderer.prepare_render(&mut imgui, &window);
imgui.update_platform_windows();
renderer
.update_viewports(&mut imgui, window_target, &glow)
.expect("Failed to update viewports");
let draw_data = imgui.render();
if let Err(e) = context.make_current(&surface) {
// For some reason make_current randomly throws errors on windows.
// Until the reason for this is found, we just print it out instead of panicing.
eprintln!("Failed to make current: {e}");
}
unsafe {
glow.disable(glow::SCISSOR_TEST);
glow.clear(glow::COLOR_BUFFER_BIT);
}
renderer
.render(&window, &glow, draw_data)
.expect("Failed to render main viewport");
surface
.swap_buffers(&context)
.expect("Failed to swap buffers");
renderer
.render_viewports(&glow, &mut imgui)
.expect("Failed to render viewports");
}
_ => {}
} }
_ => {} })
} .expect("EventLoop error");
});
} }

View File

@ -10,19 +10,23 @@ use std::{
use glow::HasContext; use glow::HasContext;
use glutin::{ use glutin::{
config::ConfigTemplateBuilder, config::ConfigTemplateBuilder,
context::{ContextAttributesBuilder, NotCurrentContext}, context::{
ContextAttributesBuilder, NotCurrentContext, NotCurrentGlContext, PossiblyCurrentGlContext,
},
display::GetGlDisplay, display::GetGlDisplay,
prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext}, prelude::GlDisplay,
surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface}, surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface},
}; };
use glutin_winit::DisplayBuilder; use glutin_winit::DisplayBuilder;
use imgui::{BackendFlags, ConfigFlags, Id, Key, MouseButton, ViewportFlags}; use imgui::{BackendFlags, ConfigFlags, Id, Io, Key, MouseButton, ViewportFlags};
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use thiserror::Error; use thiserror::Error;
use winit::{ use winit::{
dpi::{PhysicalPosition, PhysicalSize}, dpi::{PhysicalPosition, PhysicalSize},
event::{DeviceEvent, ElementState, KeyboardInput, TouchPhase, VirtualKeyCode}, event::{ElementState, TouchPhase},
event_loop::EventLoopWindowTarget, event_loop::EventLoopWindowTarget,
keyboard::{Key as WinitKey, KeyLocation, NamedKey},
platform::modifier_supplement::KeyEventExtModifierSupplement,
window::{CursorIcon, Window, WindowBuilder}, window::{CursorIcon, Window, WindowBuilder},
}; };
@ -438,163 +442,148 @@ impl Renderer {
main_window: &Window, main_window: &Window,
event: &winit::event::Event<T>, event: &winit::event::Event<T>,
) { ) {
match *event { if let winit::event::Event::WindowEvent {
winit::event::Event::WindowEvent { window_id,
window_id, ref event,
ref event, } = *event
} => { {
let (window, viewport) = if window_id == main_window.id() { let (window, viewport) = if window_id == main_window.id() {
(main_window, imgui.main_viewport_mut()) (main_window, imgui.main_viewport_mut())
} else if let Some((id, wnd)) = } else if let Some((id, wnd)) =
self.extra_windows.iter().find_map(|(id, (_, _, _, wnd))| { self.extra_windows.iter().find_map(|(id, (_, _, _, wnd))| {
if wnd.id() == window_id { if wnd.id() == window_id {
Some((*id, wnd)) Some((*id, wnd))
} else {
None
}
})
{
if let Some(viewport) = imgui.viewport_by_id_mut(id) {
(wnd, viewport)
} else { } else {
return; None
} }
})
{
if let Some(viewport) = imgui.viewport_by_id_mut(id) {
(wnd, viewport)
} else { } else {
return; return;
}; }
} else {
return;
};
match *event { match *event {
winit::event::WindowEvent::Resized(new_size) => { winit::event::WindowEvent::Resized(new_size) => {
unsafe { unsafe {
(*(viewport.platform_user_data.cast::<ViewportData>())).size = (*(viewport.platform_user_data.cast::<ViewportData>())).size =
[new_size.width as f32, new_size.height as f32]; [new_size.width as f32, new_size.height as f32];
} }
viewport.platform_request_resize = true; viewport.platform_request_resize = true;
if window_id == main_window.id() { if window_id == main_window.id() {
imgui.io_mut().display_size = imgui.io_mut().display_size =
[new_size.width as f32, new_size.height as f32]; [new_size.width as f32, new_size.height as f32];
}
}
winit::event::WindowEvent::Moved(_) => unsafe {
let new_pos = window.inner_position().unwrap().cast::<f32>();
(*(viewport.platform_user_data.cast::<ViewportData>())).pos =
[new_pos.x, new_pos.y];
viewport.platform_request_move = true;
},
winit::event::WindowEvent::CloseRequested if window_id != main_window.id() => {
viewport.platform_request_close = true;
}
winit::event::WindowEvent::Focused(f) => unsafe {
(*(viewport.platform_user_data.cast::<ViewportData>())).focus = f;
},
winit::event::WindowEvent::KeyboardInput { ref event, .. } => {
if let Some(txt) = &event.text {
for ch in txt.chars() {
imgui.io_mut().add_input_character(ch);
} }
} }
winit::event::WindowEvent::Moved(_) => unsafe {
let new_pos = window.inner_position().unwrap().cast::<f32>();
(*(viewport.platform_user_data.cast::<ViewportData>())).pos =
[new_pos.x, new_pos.y];
viewport.platform_request_move = true; let key = event.key_without_modifiers();
},
winit::event::WindowEvent::CloseRequested if window_id != main_window.id() => {
viewport.platform_request_close = true;
}
winit::event::WindowEvent::ReceivedCharacter(c) => {
imgui.io_mut().add_input_character(c);
}
winit::event::WindowEvent::Focused(f) => unsafe {
(*(viewport.platform_user_data.cast::<ViewportData>())).focus = f;
},
winit::event::WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => {
let pressed = state == ElementState::Pressed;
// We map both left and right ctrl to `ModCtrl`, etc. let pressed = event.state == ElementState::Pressed;
// imgui is told both "left control is pressed" and
// "consider the control key is pressed". Allows
// applications to use either general "ctrl" or a
// specific key. Same applies to other modifiers.
// https://github.com/ocornut/imgui/issues/5047
handle_key_modifier(imgui.io_mut(), key, pressed);
// Add main key event // We map both left and right ctrl to `ModCtrl`, etc.
if let Some(key) = to_imgui_key(key) { // imgui is told both "left control is pressed" and
imgui.io_mut().add_key_event(key, pressed); // "consider the control key is pressed". Allows
} // applications to use either general "ctrl" or a
// specific key. Same applies to other modifiers.
// https://github.com/ocornut/imgui/issues/5047
handle_key_modifier(imgui.io_mut(), &key, pressed);
// Add main key event
if let Some(key) = to_imgui_key(key, event.location) {
imgui.io_mut().add_key_event(key, pressed);
} }
winit::event::WindowEvent::ModifiersChanged(modifiers) => { }
winit::event::WindowEvent::ModifiersChanged(modifiers) => {
let state = modifiers.state();
imgui
.io_mut()
.add_key_event(Key::ModShift, state.shift_key());
imgui
.io_mut()
.add_key_event(Key::ModCtrl, state.control_key());
imgui.io_mut().add_key_event(Key::ModAlt, state.alt_key());
imgui
.io_mut()
.add_key_event(Key::ModSuper, state.super_key());
}
winit::event::WindowEvent::CursorMoved { position, .. } => {
if imgui
.io()
.config_flags
.contains(ConfigFlags::VIEWPORTS_ENABLE)
{
let window_pos = window.inner_position().unwrap_or_default().cast::<f32>();
imgui.io_mut().add_mouse_pos_event([
position.x as f32 + window_pos.x,
position.y as f32 + window_pos.y,
]);
} else {
imgui imgui
.io_mut() .io_mut()
.add_key_event(Key::ModShift, modifiers.shift()); .add_mouse_pos_event([position.x as f32, position.y as f32]);
imgui.io_mut().add_key_event(Key::ModCtrl, modifiers.ctrl());
imgui.io_mut().add_key_event(Key::ModAlt, modifiers.alt());
imgui
.io_mut()
.add_key_event(Key::ModSuper, modifiers.logo());
} }
winit::event::WindowEvent::CursorMoved { position, .. } => { }
if imgui winit::event::WindowEvent::MouseWheel {
.io() delta,
.config_flags phase: TouchPhase::Moved,
.contains(ConfigFlags::VIEWPORTS_ENABLE) ..
{ } => match delta {
let window_pos = winit::event::MouseScrollDelta::LineDelta(h, v) => {
window.inner_position().unwrap_or_default().cast::<f32>(); imgui.io_mut().add_mouse_wheel_event([h, v]);
imgui.io_mut().add_mouse_pos_event([ }
position.x as f32 + window_pos.x, winit::event::MouseScrollDelta::PixelDelta(pos) => {
position.y as f32 + window_pos.y, let h = if pos.x > 0.0 {
]); 1.0
} else if pos.x < 0.0 {
-1.0
} else { } else {
imgui 0.0
.io_mut() };
.add_mouse_pos_event([position.x as f32, position.y as f32]); let v = if pos.y > 0.0 {
} 1.0
} else if pos.y < 0.0 {
-1.0
} else {
0.0
};
imgui.io_mut().add_mouse_wheel_event([h, v]);
} }
winit::event::WindowEvent::MouseWheel { },
delta, winit::event::WindowEvent::MouseInput { state, button, .. } => {
phase: TouchPhase::Moved, let state = state == ElementState::Pressed;
..
} => match delta {
winit::event::MouseScrollDelta::LineDelta(h, v) => {
imgui.io_mut().add_mouse_wheel_event([h, v]);
}
winit::event::MouseScrollDelta::PixelDelta(pos) => {
let h = if pos.x > 0.0 {
1.0
} else if pos.x < 0.0 {
-1.0
} else {
0.0
};
let v = if pos.y > 0.0 {
1.0
} else if pos.y < 0.0 {
-1.0
} else {
0.0
};
imgui.io_mut().add_mouse_wheel_event([h, v]);
}
},
winit::event::WindowEvent::MouseInput { state, button, .. } => {
let state = state == ElementState::Pressed;
if let Some(button) = to_imgui_mouse_button(button) { if let Some(button) = to_imgui_mouse_button(button) {
imgui.io_mut().add_mouse_button_event(button, state); imgui.io_mut().add_mouse_button_event(button, state);
}
} }
_ => {}
} }
_ => {}
} }
winit::event::Event::DeviceEvent {
event:
DeviceEvent::Key(KeyboardInput {
virtual_keycode: Some(key),
state: ElementState::Released,
..
}),
..
} => {
if let Some(key) = to_imgui_key(key) {
imgui.io_mut().add_key_event(key, false);
}
}
_ => {}
} }
} }
@ -630,7 +619,7 @@ impl Renderer {
} }
ViewportEvent::SetSize(id, size) => { ViewportEvent::SetSize(id, size) => {
if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.set_inner_size(PhysicalSize::new(size[0], size[1])); _ = wnd.request_inner_size(PhysicalSize::new(size[0], size[1]));
} }
} }
ViewportEvent::SetVisible(id) => { ViewportEvent::SetVisible(id) => {
@ -663,7 +652,7 @@ impl Renderer {
imgui::MouseCursor::ResizeEW => winit::window::CursorIcon::EwResize, imgui::MouseCursor::ResizeEW => winit::window::CursorIcon::EwResize,
imgui::MouseCursor::ResizeNESW => winit::window::CursorIcon::NeswResize, imgui::MouseCursor::ResizeNESW => winit::window::CursorIcon::NeswResize,
imgui::MouseCursor::ResizeNWSE => winit::window::CursorIcon::NwseResize, imgui::MouseCursor::ResizeNWSE => winit::window::CursorIcon::NwseResize,
imgui::MouseCursor::Hand => winit::window::CursorIcon::Hand, imgui::MouseCursor::Hand => winit::window::CursorIcon::Grab,
imgui::MouseCursor::NotAllowed => winit::window::CursorIcon::NotAllowed, imgui::MouseCursor::NotAllowed => winit::window::CursorIcon::NotAllowed,
} }
} }
@ -911,15 +900,13 @@ struct PlatformBackend {
event_queue: Rc<RefCell<VecDeque<ViewportEvent>>>, event_queue: Rc<RefCell<VecDeque<ViewportEvent>>>,
} }
fn handle_key_modifier(io: &mut imgui::Io, key: VirtualKeyCode, down: bool) { fn handle_key_modifier(io: &mut Io, key: &WinitKey, down: bool) {
if key == VirtualKeyCode::LShift || key == VirtualKeyCode::RShift { match key {
io.add_key_event(imgui::Key::ModShift, down); WinitKey::Named(NamedKey::Shift) => io.add_key_event(imgui::Key::ModShift, down),
} else if key == VirtualKeyCode::LControl || key == VirtualKeyCode::RControl { WinitKey::Named(NamedKey::Control) => io.add_key_event(imgui::Key::ModCtrl, down),
io.add_key_event(imgui::Key::ModCtrl, down); WinitKey::Named(NamedKey::Alt) => io.add_key_event(imgui::Key::ModAlt, down),
} else if key == VirtualKeyCode::LAlt || key == VirtualKeyCode::RAlt { WinitKey::Named(NamedKey::Super) => io.add_key_event(imgui::Key::ModSuper, down),
io.add_key_event(imgui::Key::ModAlt, down); _ => {}
} else if key == VirtualKeyCode::LWin || key == VirtualKeyCode::RWin {
io.add_key_event(imgui::Key::ModSuper, down);
} }
} }
@ -1028,113 +1015,113 @@ impl imgui::RendererViewportBackend for RendererBackend {
fn swap_buffers(&mut self, _viewport: &mut imgui::Viewport) {} fn swap_buffers(&mut self, _viewport: &mut imgui::Viewport) {}
} }
fn to_imgui_key(keycode: VirtualKeyCode) -> Option<Key> { fn to_imgui_key(key: winit::keyboard::Key, location: KeyLocation) -> Option<Key> {
match keycode { match (key.as_ref(), location) {
VirtualKeyCode::Tab => Some(Key::Tab), (WinitKey::Named(NamedKey::Tab), _) => Some(Key::Tab),
VirtualKeyCode::Left => Some(Key::LeftArrow), (WinitKey::Named(NamedKey::ArrowLeft), _) => Some(Key::LeftArrow),
VirtualKeyCode::Right => Some(Key::RightArrow), (WinitKey::Named(NamedKey::ArrowRight), _) => Some(Key::RightArrow),
VirtualKeyCode::Up => Some(Key::UpArrow), (WinitKey::Named(NamedKey::ArrowUp), _) => Some(Key::UpArrow),
VirtualKeyCode::Down => Some(Key::DownArrow), (WinitKey::Named(NamedKey::ArrowDown), _) => Some(Key::DownArrow),
VirtualKeyCode::PageUp => Some(Key::PageUp), (WinitKey::Named(NamedKey::PageUp), _) => Some(Key::PageUp),
VirtualKeyCode::PageDown => Some(Key::PageDown), (WinitKey::Named(NamedKey::PageDown), _) => Some(Key::PageDown),
VirtualKeyCode::Home => Some(Key::Home), (WinitKey::Named(NamedKey::Home), _) => Some(Key::Home),
VirtualKeyCode::End => Some(Key::End), (WinitKey::Named(NamedKey::End), _) => Some(Key::End),
VirtualKeyCode::Insert => Some(Key::Insert), (WinitKey::Named(NamedKey::Insert), _) => Some(Key::Insert),
VirtualKeyCode::Delete => Some(Key::Delete), (WinitKey::Named(NamedKey::Delete), _) => Some(Key::Delete),
VirtualKeyCode::Back => Some(Key::Backspace), (WinitKey::Named(NamedKey::Backspace), _) => Some(Key::Backspace),
VirtualKeyCode::Space => Some(Key::Space), (WinitKey::Named(NamedKey::Space), _) => Some(Key::Space),
VirtualKeyCode::Return => Some(Key::Enter), (WinitKey::Named(NamedKey::Enter), KeyLocation::Standard) => Some(Key::Enter),
VirtualKeyCode::Escape => Some(Key::Escape), (WinitKey::Named(NamedKey::Enter), KeyLocation::Numpad) => Some(Key::KeypadEnter),
VirtualKeyCode::LControl => Some(Key::LeftCtrl), (WinitKey::Named(NamedKey::Escape), _) => Some(Key::Escape),
VirtualKeyCode::LShift => Some(Key::LeftShift), (WinitKey::Named(NamedKey::Control), KeyLocation::Left) => Some(Key::LeftCtrl),
VirtualKeyCode::LAlt => Some(Key::LeftAlt), (WinitKey::Named(NamedKey::Control), KeyLocation::Right) => Some(Key::RightCtrl),
VirtualKeyCode::LWin => Some(Key::LeftSuper), (WinitKey::Named(NamedKey::Shift), KeyLocation::Left) => Some(Key::LeftShift),
VirtualKeyCode::RControl => Some(Key::RightCtrl), (WinitKey::Named(NamedKey::Shift), KeyLocation::Right) => Some(Key::RightShift),
VirtualKeyCode::RShift => Some(Key::RightShift), (WinitKey::Named(NamedKey::Alt), KeyLocation::Left) => Some(Key::LeftAlt),
VirtualKeyCode::RAlt => Some(Key::RightAlt), (WinitKey::Named(NamedKey::Alt), KeyLocation::Right) => Some(Key::RightAlt),
VirtualKeyCode::RWin => Some(Key::RightSuper), (WinitKey::Named(NamedKey::Super), KeyLocation::Left) => Some(Key::LeftSuper),
//VirtualKeyCode::Menu => Some(Key::Menu), // TODO: find out if there is a Menu key in winit (WinitKey::Named(NamedKey::Super), KeyLocation::Right) => Some(Key::RightSuper),
VirtualKeyCode::Key0 => Some(Key::Alpha0), (WinitKey::Named(NamedKey::ContextMenu), _) => Some(Key::Menu),
VirtualKeyCode::Key1 => Some(Key::Alpha1), (WinitKey::Named(NamedKey::F1), _) => Some(Key::F1),
VirtualKeyCode::Key2 => Some(Key::Alpha2), (WinitKey::Named(NamedKey::F2), _) => Some(Key::F2),
VirtualKeyCode::Key3 => Some(Key::Alpha3), (WinitKey::Named(NamedKey::F3), _) => Some(Key::F3),
VirtualKeyCode::Key4 => Some(Key::Alpha4), (WinitKey::Named(NamedKey::F4), _) => Some(Key::F4),
VirtualKeyCode::Key5 => Some(Key::Alpha5), (WinitKey::Named(NamedKey::F5), _) => Some(Key::F5),
VirtualKeyCode::Key6 => Some(Key::Alpha6), (WinitKey::Named(NamedKey::F6), _) => Some(Key::F6),
VirtualKeyCode::Key7 => Some(Key::Alpha7), (WinitKey::Named(NamedKey::F7), _) => Some(Key::F7),
VirtualKeyCode::Key8 => Some(Key::Alpha8), (WinitKey::Named(NamedKey::F8), _) => Some(Key::F8),
VirtualKeyCode::Key9 => Some(Key::Alpha9), (WinitKey::Named(NamedKey::F9), _) => Some(Key::F9),
VirtualKeyCode::A => Some(Key::A), (WinitKey::Named(NamedKey::F10), _) => Some(Key::F10),
VirtualKeyCode::B => Some(Key::B), (WinitKey::Named(NamedKey::F11), _) => Some(Key::F11),
VirtualKeyCode::C => Some(Key::C), (WinitKey::Named(NamedKey::F12), _) => Some(Key::F12),
VirtualKeyCode::D => Some(Key::D), (WinitKey::Named(NamedKey::CapsLock), _) => Some(Key::CapsLock),
VirtualKeyCode::E => Some(Key::E), (WinitKey::Named(NamedKey::ScrollLock), _) => Some(Key::ScrollLock),
VirtualKeyCode::F => Some(Key::F), (WinitKey::Named(NamedKey::NumLock), _) => Some(Key::NumLock),
VirtualKeyCode::G => Some(Key::G), (WinitKey::Named(NamedKey::PrintScreen), _) => Some(Key::PrintScreen),
VirtualKeyCode::H => Some(Key::H), (WinitKey::Named(NamedKey::Pause), _) => Some(Key::Pause),
VirtualKeyCode::I => Some(Key::I), (WinitKey::Character("0"), KeyLocation::Standard) => Some(Key::Alpha0),
VirtualKeyCode::J => Some(Key::J), (WinitKey::Character("1"), KeyLocation::Standard) => Some(Key::Alpha1),
VirtualKeyCode::K => Some(Key::K), (WinitKey::Character("2"), KeyLocation::Standard) => Some(Key::Alpha2),
VirtualKeyCode::L => Some(Key::L), (WinitKey::Character("3"), KeyLocation::Standard) => Some(Key::Alpha3),
VirtualKeyCode::M => Some(Key::M), (WinitKey::Character("4"), KeyLocation::Standard) => Some(Key::Alpha4),
VirtualKeyCode::N => Some(Key::N), (WinitKey::Character("5"), KeyLocation::Standard) => Some(Key::Alpha5),
VirtualKeyCode::O => Some(Key::O), (WinitKey::Character("6"), KeyLocation::Standard) => Some(Key::Alpha6),
VirtualKeyCode::P => Some(Key::P), (WinitKey::Character("7"), KeyLocation::Standard) => Some(Key::Alpha7),
VirtualKeyCode::Q => Some(Key::Q), (WinitKey::Character("8"), KeyLocation::Standard) => Some(Key::Alpha8),
VirtualKeyCode::R => Some(Key::R), (WinitKey::Character("9"), KeyLocation::Standard) => Some(Key::Alpha9),
VirtualKeyCode::S => Some(Key::S), (WinitKey::Character("0"), KeyLocation::Numpad) => Some(Key::Keypad0),
VirtualKeyCode::T => Some(Key::T), (WinitKey::Character("1"), KeyLocation::Numpad) => Some(Key::Keypad1),
VirtualKeyCode::U => Some(Key::U), (WinitKey::Character("2"), KeyLocation::Numpad) => Some(Key::Keypad2),
VirtualKeyCode::V => Some(Key::V), (WinitKey::Character("3"), KeyLocation::Numpad) => Some(Key::Keypad3),
VirtualKeyCode::W => Some(Key::W), (WinitKey::Character("4"), KeyLocation::Numpad) => Some(Key::Keypad4),
VirtualKeyCode::X => Some(Key::X), (WinitKey::Character("5"), KeyLocation::Numpad) => Some(Key::Keypad5),
VirtualKeyCode::Y => Some(Key::Y), (WinitKey::Character("6"), KeyLocation::Numpad) => Some(Key::Keypad6),
VirtualKeyCode::Z => Some(Key::Z), (WinitKey::Character("7"), KeyLocation::Numpad) => Some(Key::Keypad7),
VirtualKeyCode::F1 => Some(Key::F1), (WinitKey::Character("8"), KeyLocation::Numpad) => Some(Key::Keypad8),
VirtualKeyCode::F2 => Some(Key::F2), (WinitKey::Character("9"), KeyLocation::Numpad) => Some(Key::Keypad9),
VirtualKeyCode::F3 => Some(Key::F3), (WinitKey::Character("a"), _) => Some(Key::A),
VirtualKeyCode::F4 => Some(Key::F4), (WinitKey::Character("b"), _) => Some(Key::B),
VirtualKeyCode::F5 => Some(Key::F5), (WinitKey::Character("c"), _) => Some(Key::C),
VirtualKeyCode::F6 => Some(Key::F6), (WinitKey::Character("d"), _) => Some(Key::D),
VirtualKeyCode::F7 => Some(Key::F7), (WinitKey::Character("e"), _) => Some(Key::E),
VirtualKeyCode::F8 => Some(Key::F8), (WinitKey::Character("f"), _) => Some(Key::F),
VirtualKeyCode::F9 => Some(Key::F9), (WinitKey::Character("g"), _) => Some(Key::G),
VirtualKeyCode::F10 => Some(Key::F10), (WinitKey::Character("h"), _) => Some(Key::H),
VirtualKeyCode::F11 => Some(Key::F11), (WinitKey::Character("i"), _) => Some(Key::I),
VirtualKeyCode::F12 => Some(Key::F12), (WinitKey::Character("j"), _) => Some(Key::J),
VirtualKeyCode::Apostrophe => Some(Key::Apostrophe), (WinitKey::Character("k"), _) => Some(Key::K),
VirtualKeyCode::Comma => Some(Key::Comma), (WinitKey::Character("l"), _) => Some(Key::L),
VirtualKeyCode::Minus => Some(Key::Minus), (WinitKey::Character("m"), _) => Some(Key::M),
VirtualKeyCode::Period => Some(Key::Period), (WinitKey::Character("n"), _) => Some(Key::N),
VirtualKeyCode::Slash => Some(Key::Slash), (WinitKey::Character("o"), _) => Some(Key::O),
VirtualKeyCode::Semicolon => Some(Key::Semicolon), (WinitKey::Character("p"), _) => Some(Key::P),
VirtualKeyCode::Equals => Some(Key::Equal), (WinitKey::Character("q"), _) => Some(Key::Q),
VirtualKeyCode::LBracket => Some(Key::LeftBracket), (WinitKey::Character("r"), _) => Some(Key::R),
VirtualKeyCode::Backslash => Some(Key::Backslash), (WinitKey::Character("s"), _) => Some(Key::S),
VirtualKeyCode::RBracket => Some(Key::RightBracket), (WinitKey::Character("t"), _) => Some(Key::T),
VirtualKeyCode::Grave => Some(Key::GraveAccent), (WinitKey::Character("u"), _) => Some(Key::U),
VirtualKeyCode::Capital => Some(Key::CapsLock), (WinitKey::Character("v"), _) => Some(Key::V),
VirtualKeyCode::Scroll => Some(Key::ScrollLock), (WinitKey::Character("w"), _) => Some(Key::W),
VirtualKeyCode::Numlock => Some(Key::NumLock), (WinitKey::Character("x"), _) => Some(Key::X),
VirtualKeyCode::Snapshot => Some(Key::PrintScreen), (WinitKey::Character("y"), _) => Some(Key::Y),
VirtualKeyCode::Pause => Some(Key::Pause), (WinitKey::Character("z"), _) => Some(Key::Z),
VirtualKeyCode::Numpad0 => Some(Key::Keypad0), (WinitKey::Character("'"), _) => Some(Key::Apostrophe),
VirtualKeyCode::Numpad1 => Some(Key::Keypad1), (WinitKey::Character(","), KeyLocation::Standard) => Some(Key::Comma),
VirtualKeyCode::Numpad2 => Some(Key::Keypad2), (WinitKey::Character("-"), KeyLocation::Standard) => Some(Key::Minus),
VirtualKeyCode::Numpad3 => Some(Key::Keypad3), (WinitKey::Character("-"), KeyLocation::Numpad) => Some(Key::KeypadSubtract),
VirtualKeyCode::Numpad4 => Some(Key::Keypad4), (WinitKey::Character("."), KeyLocation::Standard) => Some(Key::Period),
VirtualKeyCode::Numpad5 => Some(Key::Keypad5), (WinitKey::Character("."), KeyLocation::Numpad) => Some(Key::KeypadDecimal),
VirtualKeyCode::Numpad6 => Some(Key::Keypad6), (WinitKey::Character("/"), KeyLocation::Standard) => Some(Key::Slash),
VirtualKeyCode::Numpad7 => Some(Key::Keypad7), (WinitKey::Character("/"), KeyLocation::Numpad) => Some(Key::KeypadDivide),
VirtualKeyCode::Numpad8 => Some(Key::Keypad8), (WinitKey::Character(";"), _) => Some(Key::Semicolon),
VirtualKeyCode::Numpad9 => Some(Key::Keypad9), (WinitKey::Character("="), KeyLocation::Standard) => Some(Key::Equal),
VirtualKeyCode::NumpadDecimal => Some(Key::KeypadDecimal), (WinitKey::Character("="), KeyLocation::Numpad) => Some(Key::KeypadEqual),
VirtualKeyCode::NumpadDivide => Some(Key::KeypadDivide), (WinitKey::Character("["), _) => Some(Key::LeftBracket),
VirtualKeyCode::NumpadMultiply => Some(Key::KeypadMultiply), (WinitKey::Character("\\"), _) => Some(Key::Backslash),
VirtualKeyCode::NumpadSubtract => Some(Key::KeypadSubtract), (WinitKey::Character("]"), _) => Some(Key::RightBracket),
VirtualKeyCode::NumpadAdd => Some(Key::KeypadAdd), (WinitKey::Character("`"), _) => Some(Key::GraveAccent),
VirtualKeyCode::NumpadEnter => Some(Key::KeypadEnter), (WinitKey::Character("*"), KeyLocation::Numpad) => Some(Key::KeypadMultiply),
VirtualKeyCode::NumpadEquals => Some(Key::KeypadEqual), (WinitKey::Character("+"), KeyLocation::Numpad) => Some(Key::KeypadAdd),
_ => None, _ => None,
} }
} }

View File

@ -11,4 +11,4 @@ categories = ["gui"]
[dependencies] [dependencies]
imgui = { version = "0.11.0", path = "../imgui" } imgui = { version = "0.11.0", path = "../imgui" }
winit = { version = "0.27.2", default-features = false } winit = { version = "0.29.3", default-features = false }

View File

@ -23,7 +23,7 @@
//! use winit::event_loop::{ControlFlow, EventLoop}; //! use winit::event_loop::{ControlFlow, EventLoop};
//! use winit::window::Window; //! use winit::window::Window;
//! //!
//! let mut event_loop = EventLoop::new(); //! let mut event_loop = EventLoop::new().expect("Failed to create EventLoop");
//! let mut window = Window::new(&event_loop).unwrap(); //! let mut window = Window::new(&event_loop).unwrap();
//! //!
//! let mut imgui = Context::create(); //! let mut imgui = Context::create();
@ -34,7 +34,7 @@
//! //!
//! let mut last_frame = Instant::now(); //! let mut last_frame = Instant::now();
//! let mut run = true; //! let mut run = true;
//! event_loop.run(move |event, _, control_flow| { //! event_loop.run(move |event, window_target| {
//! match event { //! match event {
//! Event::NewEvents(_) => { //! Event::NewEvents(_) => {
//! // other application-specific logic //! // other application-specific logic
@ -42,13 +42,13 @@
//! imgui.io_mut().update_delta_time(now - last_frame); //! imgui.io_mut().update_delta_time(now - last_frame);
//! last_frame = now; //! last_frame = now;
//! }, //! },
//! Event::MainEventsCleared => { //! Event::AboutToWait => {
//! // other application-specific logic //! // other application-specific logic
//! platform.prepare_frame(imgui.io_mut(), &window) // step 4 //! platform.prepare_frame(imgui.io_mut(), &window) // step 4
//! .expect("Failed to prepare frame"); //! .expect("Failed to prepare frame");
//! window.request_redraw(); //! window.request_redraw();
//! } //! }
//! Event::RedrawRequested(_) => { //! Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } => {
//! let ui = imgui.frame(); //! let ui = imgui.frame();
//! // application-specific rendering *under the UI* //! // application-specific rendering *under the UI*
//! //!
@ -62,7 +62,7 @@
//! // application-specific rendering *over the UI* //! // application-specific rendering *over the UI*
//! }, //! },
//! Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { //! Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
//! *control_flow = ControlFlow::Exit; //! window_target.exit();
//! } //! }
//! // other application-specific event handling //! // other application-specific event handling
//! event => { //! event => {
@ -70,7 +70,7 @@
//! // other application-specific event handling //! // other application-specific event handling
//! } //! }
//! } //! }
//! }) //! }).expect("EventLoop error");
//! ``` //! ```
use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui}; use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui};
@ -78,14 +78,15 @@ use std::cmp::Ordering;
// Re-export winit to make it easier for users to use the correct version. // Re-export winit to make it easier for users to use the correct version.
pub use winit; pub use winit;
use winit::dpi::{LogicalPosition, LogicalSize}; use winit::{
dpi::{LogicalPosition, LogicalSize},
keyboard::{Key as WinitKey, KeyLocation, NamedKey},
platform::modifier_supplement::KeyEventExtModifierSupplement,
};
use winit::{ use winit::{
error::ExternalError, error::ExternalError,
event::{ event::{ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent},
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
VirtualKeyCode, WindowEvent,
},
window::{CursorIcon as MouseCursor, Window}, window::{CursorIcon as MouseCursor, Window},
}; };
@ -112,7 +113,7 @@ fn to_winit_cursor(cursor: imgui::MouseCursor) -> MouseCursor {
imgui::MouseCursor::ResizeEW => MouseCursor::EwResize, imgui::MouseCursor::ResizeEW => MouseCursor::EwResize,
imgui::MouseCursor::ResizeNESW => MouseCursor::NeswResize, imgui::MouseCursor::ResizeNESW => MouseCursor::NeswResize,
imgui::MouseCursor::ResizeNWSE => MouseCursor::NwseResize, imgui::MouseCursor::ResizeNWSE => MouseCursor::NwseResize,
imgui::MouseCursor::Hand => MouseCursor::Hand, imgui::MouseCursor::Hand => MouseCursor::Grab,
imgui::MouseCursor::NotAllowed => MouseCursor::NotAllowed, imgui::MouseCursor::NotAllowed => MouseCursor::NotAllowed,
} }
} }
@ -180,126 +181,124 @@ fn to_imgui_mouse_button(button: MouseButton) -> Option<imgui::MouseButton> {
} }
} }
fn to_imgui_key(keycode: VirtualKeyCode) -> Option<Key> { fn to_imgui_key(key: winit::keyboard::Key, location: KeyLocation) -> Option<Key> {
match keycode { match (key.as_ref(), location) {
VirtualKeyCode::Tab => Some(Key::Tab), (WinitKey::Named(NamedKey::Tab), _) => Some(Key::Tab),
VirtualKeyCode::Left => Some(Key::LeftArrow), (WinitKey::Named(NamedKey::ArrowLeft), _) => Some(Key::LeftArrow),
VirtualKeyCode::Right => Some(Key::RightArrow), (WinitKey::Named(NamedKey::ArrowRight), _) => Some(Key::RightArrow),
VirtualKeyCode::Up => Some(Key::UpArrow), (WinitKey::Named(NamedKey::ArrowUp), _) => Some(Key::UpArrow),
VirtualKeyCode::Down => Some(Key::DownArrow), (WinitKey::Named(NamedKey::ArrowDown), _) => Some(Key::DownArrow),
VirtualKeyCode::PageUp => Some(Key::PageUp), (WinitKey::Named(NamedKey::PageUp), _) => Some(Key::PageUp),
VirtualKeyCode::PageDown => Some(Key::PageDown), (WinitKey::Named(NamedKey::PageDown), _) => Some(Key::PageDown),
VirtualKeyCode::Home => Some(Key::Home), (WinitKey::Named(NamedKey::Home), _) => Some(Key::Home),
VirtualKeyCode::End => Some(Key::End), (WinitKey::Named(NamedKey::End), _) => Some(Key::End),
VirtualKeyCode::Insert => Some(Key::Insert), (WinitKey::Named(NamedKey::Insert), _) => Some(Key::Insert),
VirtualKeyCode::Delete => Some(Key::Delete), (WinitKey::Named(NamedKey::Delete), _) => Some(Key::Delete),
VirtualKeyCode::Back => Some(Key::Backspace), (WinitKey::Named(NamedKey::Backspace), _) => Some(Key::Backspace),
VirtualKeyCode::Space => Some(Key::Space), (WinitKey::Named(NamedKey::Space), _) => Some(Key::Space),
VirtualKeyCode::Return => Some(Key::Enter), (WinitKey::Named(NamedKey::Enter), KeyLocation::Standard) => Some(Key::Enter),
VirtualKeyCode::Escape => Some(Key::Escape), (WinitKey::Named(NamedKey::Enter), KeyLocation::Numpad) => Some(Key::KeypadEnter),
VirtualKeyCode::LControl => Some(Key::LeftCtrl), (WinitKey::Named(NamedKey::Escape), _) => Some(Key::Escape),
VirtualKeyCode::LShift => Some(Key::LeftShift), (WinitKey::Named(NamedKey::Control), KeyLocation::Left) => Some(Key::LeftCtrl),
VirtualKeyCode::LAlt => Some(Key::LeftAlt), (WinitKey::Named(NamedKey::Control), KeyLocation::Right) => Some(Key::RightCtrl),
VirtualKeyCode::LWin => Some(Key::LeftSuper), (WinitKey::Named(NamedKey::Shift), KeyLocation::Left) => Some(Key::LeftShift),
VirtualKeyCode::RControl => Some(Key::RightCtrl), (WinitKey::Named(NamedKey::Shift), KeyLocation::Right) => Some(Key::RightShift),
VirtualKeyCode::RShift => Some(Key::RightShift), (WinitKey::Named(NamedKey::Alt), KeyLocation::Left) => Some(Key::LeftAlt),
VirtualKeyCode::RAlt => Some(Key::RightAlt), (WinitKey::Named(NamedKey::Alt), KeyLocation::Right) => Some(Key::RightAlt),
VirtualKeyCode::RWin => Some(Key::RightSuper), (WinitKey::Named(NamedKey::Super), KeyLocation::Left) => Some(Key::LeftSuper),
//VirtualKeyCode::Menu => Some(Key::Menu), // TODO: find out if there is a Menu key in winit (WinitKey::Named(NamedKey::Super), KeyLocation::Right) => Some(Key::RightSuper),
VirtualKeyCode::Key0 => Some(Key::Alpha0), (WinitKey::Named(NamedKey::ContextMenu), _) => Some(Key::Menu),
VirtualKeyCode::Key1 => Some(Key::Alpha1), (WinitKey::Named(NamedKey::F1), _) => Some(Key::F1),
VirtualKeyCode::Key2 => Some(Key::Alpha2), (WinitKey::Named(NamedKey::F2), _) => Some(Key::F2),
VirtualKeyCode::Key3 => Some(Key::Alpha3), (WinitKey::Named(NamedKey::F3), _) => Some(Key::F3),
VirtualKeyCode::Key4 => Some(Key::Alpha4), (WinitKey::Named(NamedKey::F4), _) => Some(Key::F4),
VirtualKeyCode::Key5 => Some(Key::Alpha5), (WinitKey::Named(NamedKey::F5), _) => Some(Key::F5),
VirtualKeyCode::Key6 => Some(Key::Alpha6), (WinitKey::Named(NamedKey::F6), _) => Some(Key::F6),
VirtualKeyCode::Key7 => Some(Key::Alpha7), (WinitKey::Named(NamedKey::F7), _) => Some(Key::F7),
VirtualKeyCode::Key8 => Some(Key::Alpha8), (WinitKey::Named(NamedKey::F8), _) => Some(Key::F8),
VirtualKeyCode::Key9 => Some(Key::Alpha9), (WinitKey::Named(NamedKey::F9), _) => Some(Key::F9),
VirtualKeyCode::A => Some(Key::A), (WinitKey::Named(NamedKey::F10), _) => Some(Key::F10),
VirtualKeyCode::B => Some(Key::B), (WinitKey::Named(NamedKey::F11), _) => Some(Key::F11),
VirtualKeyCode::C => Some(Key::C), (WinitKey::Named(NamedKey::F12), _) => Some(Key::F12),
VirtualKeyCode::D => Some(Key::D), (WinitKey::Named(NamedKey::CapsLock), _) => Some(Key::CapsLock),
VirtualKeyCode::E => Some(Key::E), (WinitKey::Named(NamedKey::ScrollLock), _) => Some(Key::ScrollLock),
VirtualKeyCode::F => Some(Key::F), (WinitKey::Named(NamedKey::NumLock), _) => Some(Key::NumLock),
VirtualKeyCode::G => Some(Key::G), (WinitKey::Named(NamedKey::PrintScreen), _) => Some(Key::PrintScreen),
VirtualKeyCode::H => Some(Key::H), (WinitKey::Named(NamedKey::Pause), _) => Some(Key::Pause),
VirtualKeyCode::I => Some(Key::I), (WinitKey::Character("0"), KeyLocation::Standard) => Some(Key::Alpha0),
VirtualKeyCode::J => Some(Key::J), (WinitKey::Character("1"), KeyLocation::Standard) => Some(Key::Alpha1),
VirtualKeyCode::K => Some(Key::K), (WinitKey::Character("2"), KeyLocation::Standard) => Some(Key::Alpha2),
VirtualKeyCode::L => Some(Key::L), (WinitKey::Character("3"), KeyLocation::Standard) => Some(Key::Alpha3),
VirtualKeyCode::M => Some(Key::M), (WinitKey::Character("4"), KeyLocation::Standard) => Some(Key::Alpha4),
VirtualKeyCode::N => Some(Key::N), (WinitKey::Character("5"), KeyLocation::Standard) => Some(Key::Alpha5),
VirtualKeyCode::O => Some(Key::O), (WinitKey::Character("6"), KeyLocation::Standard) => Some(Key::Alpha6),
VirtualKeyCode::P => Some(Key::P), (WinitKey::Character("7"), KeyLocation::Standard) => Some(Key::Alpha7),
VirtualKeyCode::Q => Some(Key::Q), (WinitKey::Character("8"), KeyLocation::Standard) => Some(Key::Alpha8),
VirtualKeyCode::R => Some(Key::R), (WinitKey::Character("9"), KeyLocation::Standard) => Some(Key::Alpha9),
VirtualKeyCode::S => Some(Key::S), (WinitKey::Character("0"), KeyLocation::Numpad) => Some(Key::Keypad0),
VirtualKeyCode::T => Some(Key::T), (WinitKey::Character("1"), KeyLocation::Numpad) => Some(Key::Keypad1),
VirtualKeyCode::U => Some(Key::U), (WinitKey::Character("2"), KeyLocation::Numpad) => Some(Key::Keypad2),
VirtualKeyCode::V => Some(Key::V), (WinitKey::Character("3"), KeyLocation::Numpad) => Some(Key::Keypad3),
VirtualKeyCode::W => Some(Key::W), (WinitKey::Character("4"), KeyLocation::Numpad) => Some(Key::Keypad4),
VirtualKeyCode::X => Some(Key::X), (WinitKey::Character("5"), KeyLocation::Numpad) => Some(Key::Keypad5),
VirtualKeyCode::Y => Some(Key::Y), (WinitKey::Character("6"), KeyLocation::Numpad) => Some(Key::Keypad6),
VirtualKeyCode::Z => Some(Key::Z), (WinitKey::Character("7"), KeyLocation::Numpad) => Some(Key::Keypad7),
VirtualKeyCode::F1 => Some(Key::F1), (WinitKey::Character("8"), KeyLocation::Numpad) => Some(Key::Keypad8),
VirtualKeyCode::F2 => Some(Key::F2), (WinitKey::Character("9"), KeyLocation::Numpad) => Some(Key::Keypad9),
VirtualKeyCode::F3 => Some(Key::F3), (WinitKey::Character("a"), _) => Some(Key::A),
VirtualKeyCode::F4 => Some(Key::F4), (WinitKey::Character("b"), _) => Some(Key::B),
VirtualKeyCode::F5 => Some(Key::F5), (WinitKey::Character("c"), _) => Some(Key::C),
VirtualKeyCode::F6 => Some(Key::F6), (WinitKey::Character("d"), _) => Some(Key::D),
VirtualKeyCode::F7 => Some(Key::F7), (WinitKey::Character("e"), _) => Some(Key::E),
VirtualKeyCode::F8 => Some(Key::F8), (WinitKey::Character("f"), _) => Some(Key::F),
VirtualKeyCode::F9 => Some(Key::F9), (WinitKey::Character("g"), _) => Some(Key::G),
VirtualKeyCode::F10 => Some(Key::F10), (WinitKey::Character("h"), _) => Some(Key::H),
VirtualKeyCode::F11 => Some(Key::F11), (WinitKey::Character("i"), _) => Some(Key::I),
VirtualKeyCode::F12 => Some(Key::F12), (WinitKey::Character("j"), _) => Some(Key::J),
VirtualKeyCode::Apostrophe => Some(Key::Apostrophe), (WinitKey::Character("k"), _) => Some(Key::K),
VirtualKeyCode::Comma => Some(Key::Comma), (WinitKey::Character("l"), _) => Some(Key::L),
VirtualKeyCode::Minus => Some(Key::Minus), (WinitKey::Character("m"), _) => Some(Key::M),
VirtualKeyCode::Period => Some(Key::Period), (WinitKey::Character("n"), _) => Some(Key::N),
VirtualKeyCode::Slash => Some(Key::Slash), (WinitKey::Character("o"), _) => Some(Key::O),
VirtualKeyCode::Semicolon => Some(Key::Semicolon), (WinitKey::Character("p"), _) => Some(Key::P),
VirtualKeyCode::Equals => Some(Key::Equal), (WinitKey::Character("q"), _) => Some(Key::Q),
VirtualKeyCode::LBracket => Some(Key::LeftBracket), (WinitKey::Character("r"), _) => Some(Key::R),
VirtualKeyCode::Backslash => Some(Key::Backslash), (WinitKey::Character("s"), _) => Some(Key::S),
VirtualKeyCode::RBracket => Some(Key::RightBracket), (WinitKey::Character("t"), _) => Some(Key::T),
VirtualKeyCode::Grave => Some(Key::GraveAccent), (WinitKey::Character("u"), _) => Some(Key::U),
VirtualKeyCode::Capital => Some(Key::CapsLock), (WinitKey::Character("v"), _) => Some(Key::V),
VirtualKeyCode::Scroll => Some(Key::ScrollLock), (WinitKey::Character("w"), _) => Some(Key::W),
VirtualKeyCode::Numlock => Some(Key::NumLock), (WinitKey::Character("x"), _) => Some(Key::X),
VirtualKeyCode::Snapshot => Some(Key::PrintScreen), (WinitKey::Character("y"), _) => Some(Key::Y),
VirtualKeyCode::Pause => Some(Key::Pause), (WinitKey::Character("z"), _) => Some(Key::Z),
VirtualKeyCode::Numpad0 => Some(Key::Keypad0), (WinitKey::Character("'"), _) => Some(Key::Apostrophe),
VirtualKeyCode::Numpad1 => Some(Key::Keypad1), (WinitKey::Character(","), KeyLocation::Standard) => Some(Key::Comma),
VirtualKeyCode::Numpad2 => Some(Key::Keypad2), (WinitKey::Character("-"), KeyLocation::Standard) => Some(Key::Minus),
VirtualKeyCode::Numpad3 => Some(Key::Keypad3), (WinitKey::Character("-"), KeyLocation::Numpad) => Some(Key::KeypadSubtract),
VirtualKeyCode::Numpad4 => Some(Key::Keypad4), (WinitKey::Character("."), KeyLocation::Standard) => Some(Key::Period),
VirtualKeyCode::Numpad5 => Some(Key::Keypad5), (WinitKey::Character("."), KeyLocation::Numpad) => Some(Key::KeypadDecimal),
VirtualKeyCode::Numpad6 => Some(Key::Keypad6), (WinitKey::Character("/"), KeyLocation::Standard) => Some(Key::Slash),
VirtualKeyCode::Numpad7 => Some(Key::Keypad7), (WinitKey::Character("/"), KeyLocation::Numpad) => Some(Key::KeypadDivide),
VirtualKeyCode::Numpad8 => Some(Key::Keypad8), (WinitKey::Character(";"), _) => Some(Key::Semicolon),
VirtualKeyCode::Numpad9 => Some(Key::Keypad9), (WinitKey::Character("="), KeyLocation::Standard) => Some(Key::Equal),
VirtualKeyCode::NumpadDecimal => Some(Key::KeypadDecimal), (WinitKey::Character("="), KeyLocation::Numpad) => Some(Key::KeypadEqual),
VirtualKeyCode::NumpadDivide => Some(Key::KeypadDivide), (WinitKey::Character("["), _) => Some(Key::LeftBracket),
VirtualKeyCode::NumpadMultiply => Some(Key::KeypadMultiply), (WinitKey::Character("\\"), _) => Some(Key::Backslash),
VirtualKeyCode::NumpadSubtract => Some(Key::KeypadSubtract), (WinitKey::Character("]"), _) => Some(Key::RightBracket),
VirtualKeyCode::NumpadAdd => Some(Key::KeypadAdd), (WinitKey::Character("`"), _) => Some(Key::GraveAccent),
VirtualKeyCode::NumpadEnter => Some(Key::KeypadEnter), (WinitKey::Character("*"), KeyLocation::Numpad) => Some(Key::KeypadMultiply),
VirtualKeyCode::NumpadEquals => Some(Key::KeypadEqual), (WinitKey::Character("+"), KeyLocation::Numpad) => Some(Key::KeypadAdd),
_ => None, _ => None,
} }
} }
fn handle_key_modifier(io: &mut Io, key: VirtualKeyCode, down: bool) { fn handle_key_modifier(io: &mut Io, key: &WinitKey, down: bool) {
if key == VirtualKeyCode::LShift || key == VirtualKeyCode::RShift { match key {
io.add_key_event(imgui::Key::ModShift, down); WinitKey::Named(NamedKey::Shift) => io.add_key_event(imgui::Key::ModShift, down),
} else if key == VirtualKeyCode::LControl || key == VirtualKeyCode::RControl { WinitKey::Named(NamedKey::Control) => io.add_key_event(imgui::Key::ModCtrl, down),
io.add_key_event(imgui::Key::ModCtrl, down); WinitKey::Named(NamedKey::Alt) => io.add_key_event(imgui::Key::ModAlt, down),
} else if key == VirtualKeyCode::LAlt || key == VirtualKeyCode::RAlt { WinitKey::Named(NamedKey::Super) => io.add_key_event(imgui::Key::ModSuper, down),
io.add_key_event(imgui::Key::ModAlt, down); _ => {}
} else if key == VirtualKeyCode::LWin || key == VirtualKeyCode::RWin {
io.add_key_event(imgui::Key::ModSuper, down);
} }
} }
@ -411,19 +410,18 @@ impl WinitPlatform {
} }
// Track key release events outside our window. If we don't do this, // Track key release events outside our window. If we don't do this,
// we might never see the release event if some other window gets focus. // we might never see the release event if some other window gets focus.
Event::DeviceEvent { // Event::DeviceEvent {
event: // event:
DeviceEvent::Key(KeyboardInput { // DeviceEvent::Key(RawKeyEvent {
state: ElementState::Released, // physical_key,
virtual_keycode: Some(key), // state: ElementState::Released,
.. // }),
}), // ..
.. // } => {
} => { // if let Some(key) = to_imgui_key(key) {
if let Some(key) = to_imgui_key(key) { // io.add_key_event(key, false);
io.add_key_event(key, false); // }
} // }
}
_ => (), _ => (),
} }
} }
@ -456,24 +454,26 @@ impl WinitPlatform {
io.display_size = [logical_size.width as f32, logical_size.height as f32]; io.display_size = [logical_size.width as f32, logical_size.height as f32];
} }
WindowEvent::ModifiersChanged(modifiers) => { WindowEvent::ModifiersChanged(modifiers) => {
let state = modifiers.state();
// We need to track modifiers separately because some system like macOS, will // We need to track modifiers separately because some system like macOS, will
// not reliably send modifier states during certain events like ScreenCapture. // not reliably send modifier states during certain events like ScreenCapture.
// Gotta let the people show off their pretty imgui widgets! // Gotta let the people show off their pretty imgui widgets!
io.add_key_event(Key::ModShift, modifiers.shift()); io.add_key_event(Key::ModShift, state.shift_key());
io.add_key_event(Key::ModCtrl, modifiers.ctrl()); io.add_key_event(Key::ModCtrl, state.control_key());
io.add_key_event(Key::ModAlt, modifiers.alt()); io.add_key_event(Key::ModAlt, state.alt_key());
io.add_key_event(Key::ModSuper, modifiers.logo()); io.add_key_event(Key::ModSuper, state.super_key());
} }
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput { ref event, .. } => {
input: if let Some(txt) = &event.text {
KeyboardInput { for ch in txt.chars() {
virtual_keycode: Some(key), if ch != '\u{7f}' {
state, io.add_input_character(ch)
.. }
}, }
.. }
} => {
let pressed = state == ElementState::Pressed; let key = event.key_without_modifiers();
let pressed = event.state == ElementState::Pressed;
// We map both left and right ctrl to `ModCtrl`, etc. // We map both left and right ctrl to `ModCtrl`, etc.
// imgui is told both "left control is pressed" and // imgui is told both "left control is pressed" and
@ -481,20 +481,15 @@ impl WinitPlatform {
// applications to use either general "ctrl" or a // applications to use either general "ctrl" or a
// specific key. Same applies to other modifiers. // specific key. Same applies to other modifiers.
// https://github.com/ocornut/imgui/issues/5047 // https://github.com/ocornut/imgui/issues/5047
handle_key_modifier(io, key, pressed); handle_key_modifier(io, &key, pressed);
println!("KEY EVENT: {event:?}");
// Add main key event // Add main key event
if let Some(key) = to_imgui_key(key) { if let Some(key) = to_imgui_key(key, event.location) {
io.add_key_event(key, pressed); io.add_key_event(key, pressed);
} }
} }
WindowEvent::ReceivedCharacter(ch) => {
// Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
// delete it.
if ch != '\u{7f}' {
io.add_input_character(ch)
}
}
WindowEvent::CursorMoved { position, .. } => { WindowEvent::CursorMoved { position, .. } => {
let position = position.to_logical(window.scale_factor()); let position = position.to_logical(window.scale_factor());
let position = self.scale_pos_from_winit(window, position); let position = self.scale_pos_from_winit(window, position);