use torophy::{Space}; use glium::glutin; use glium::glutin::event::{Event, WindowEvent, DeviceEvent, VirtualKeyCode, ElementState}; use glium::glutin::event_loop::{ControlFlow, EventLoop}; use glium::glutin::window::WindowBuilder; use glium::Surface; use imgui_glium_renderer::Renderer; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use std::time::{Instant, Duration}; mod drawing; mod renderer; pub struct GraphicMonitor { display: glium::Display, event_loop: EventLoop<()>, renderer: renderer::Renderer, imgui: imgui::Context, imgui_renderer: Renderer, imgui_platform: WinitPlatform, space: Space, } impl GraphicMonitor { pub fn new(space: Space) -> GraphicMonitor { let dimension = space.bounds().dimension(); let window_builder = WindowBuilder::new() .with_title("Torophy monitor") .with_inner_size(glutin::dpi::LogicalSize::new(dimension.x, dimension.y)); let glutin_context = glutin::ContextBuilder::new() .with_multisampling(8) .with_vsync(true); let event_loop = EventLoop::new(); let display = glium::Display::new(window_builder, glutin_context, &event_loop) .expect("Failed to initialize glium display"); let renderer = renderer::Renderer::new(&display, (dimension.x, dimension.y)); let mut imgui = imgui::Context::create(); imgui.set_ini_filename(None); let mut imgui_platform = WinitPlatform::init(&mut imgui); { let gl_window = display.gl_window(); let window = gl_window.window(); imgui_platform.attach_window(imgui.io_mut(), &window, HiDpiMode::Rounded); } let hidpi_factor = imgui_platform.hidpi_factor(); let font_size = (13.0 * hidpi_factor) as f32; imgui.fonts().add_font(&[ imgui::FontSource::DefaultFontData { config: Some(imgui::FontConfig { size_pixels: font_size, ..imgui::FontConfig::default() }), }, ]); imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32; let imgui_renderer = Renderer::init(&mut imgui, &display) .expect("Failed to initialize imgui renderer"); GraphicMonitor { display, event_loop, renderer, imgui, imgui_renderer, imgui_platform, space, } } pub fn main_loop(self, mut frame_action: F) where F: 'static + FnMut(&mut Space) { let GraphicMonitor { display, event_loop, renderer, mut imgui, mut imgui_renderer, mut imgui_platform, mut space } = self; let mut last_frame = Instant::now(); let mut last_physics_time = Duration::from_secs(0); let mut ctrl_key = false; event_loop.run(move |event, _, control_flow| { let gl_window = display.gl_window(); match event { Event::NewEvents(_) => { last_frame = imgui.io_mut().update_delta_time(last_frame); frame_action(&mut space); last_physics_time = Instant::now() - last_frame; }, Event::MainEventsCleared => { imgui_platform.prepare_frame(imgui.io_mut(), &gl_window.window()) .expect("Failed to prepare frame"); gl_window.window().request_redraw(); } Event::RedrawRequested(_) => { let mut target = display.draw(); target.clear_color(0.0, 0.0, 0.0, 1.0); drawing::draw_space(&renderer, &mut target, &space); let mut imgui_ui = imgui.frame(); drawing::draw_ui(&mut imgui_ui, &space, last_physics_time); imgui_platform.prepare_render(&imgui_ui, gl_window.window()); let imgui_draw_data = imgui_ui.render(); imgui_renderer.render(&mut target, imgui_draw_data).expect("Rendering failed"); target.finish().unwrap(); } Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, Event::DeviceEvent { event: DeviceEvent::ModifiersChanged(modifiers), .. } => { ctrl_key = modifiers.ctrl() }, Event::DeviceEvent { event: DeviceEvent::Key(input), .. } => { if input.virtual_keycode == Some(VirtualKeyCode::W) && input.state == ElementState::Pressed && ctrl_key { *control_flow = ControlFlow::Exit } } event => { imgui_platform.handle_event(imgui.io_mut(), gl_window.window(), &event); } }; }); } }