use glium::glutin; use glium::glutin::event::{Event, WindowEvent}; 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_glium_renderer::Renderer; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use std::path::Path; use std::time::Instant; mod clipboard; pub struct System { pub event_loop: EventLoop<()>, pub display: glium::Display, pub imgui: Context, pub platform: WinitPlatform, pub renderer: Renderer, pub font_size: f32, } pub fn init(title: &str) -> System { let title = match Path::new(&title).file_name() { Some(file_name) => file_name.to_str().unwrap(), None => title, }; let event_loop = EventLoop::new(); let context = glutin::ContextBuilder::new().with_vsync(true); let builder = WindowBuilder::new() .with_title(title.to_owned()) .with_inner_size(glutin::dpi::LogicalSize::new(1024f64, 768f64)); let display = Display::new(builder, context, &event_loop).expect("Failed to initialize display"); let mut imgui = Context::create(); imgui.set_ini_filename(None); if let Some(backend) = clipboard::init() { imgui.set_clipboard_backend(Box::new(backend)); } else { eprintln!("Failed to initialize clipboard"); } let mut platform = WinitPlatform::init(&mut imgui); { let gl_window = display.gl_window(); let window = gl_window.window(); platform.attach_window(imgui.io_mut(), window, HiDpiMode::Rounded); } let hidpi_factor = platform.hidpi_factor(); let font_size = (13.0 * hidpi_factor) as f32; // imgui.fonts().add_font(&[ // FontSource::DefaultFontData { // config: Some(FontConfig { // size_pixels: font_size, // ..FontConfig::default() // }), // }, // FontSource::TtfData { // data: include_bytes!("../../../resources/mplus-1p-regular.ttf"), // size_pixels: font_size, // config: Some(FontConfig { // rasterizer_multiply: 1.75, // glyph_ranges: FontGlyphRanges::japanese(), // ..FontConfig::default() // }), // }, // ]); imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32; let renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer"); System { event_loop, display, imgui, platform, renderer, font_size, } } impl System { pub fn main_loop(self, mut run_ui: F) { let System { event_loop, display, mut imgui, mut platform, mut renderer, .. } = self; let mut last_frame = Instant::now(); event_loop.run(move |event, _, control_flow| match event { Event::NewEvents(_) => { let now = Instant::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 mut ui = imgui.frame(); let mut run = true; run_ui(&mut run, &mut ui); if !run { *control_flow = ControlFlow::Exit; } let gl_window = display.gl_window(); let mut target = display.draw(); target.clear_color_srgb(0.7, 0.7, 0.7, 0.7); platform.prepare_render(&ui, gl_window.window()); let draw_data = ui.render(); renderer .render(&mut target, draw_data) .expect("Rendering failed"); target.finish().expect("Failed to swap buffers"); } Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, event => { let gl_window = display.gl_window(); platform.handle_event(imgui.io_mut(), gl_window.window(), &event); } }) } }