From baf60f152322d3fcbee234646ec1f99fc2e6487e Mon Sep 17 00:00:00 2001 From: Piotr Date: Tue, 29 Sep 2020 20:25:52 +0200 Subject: [PATCH] Working imgui --- Cargo.lock | 24 ++-- Cargo.toml | 9 +- src/example_client.rs | 9 +- src/gaia/camera.rs | 2 +- src/gaia/client.rs | 6 +- src/gaia/components.rs | 2 +- src/gaia/engine.rs | 263 +++++++++++++++++++++++++++++++-------- src/gaia/imgui_helper.rs | 2 +- src/gaia/light.rs | 2 +- src/main.rs | 2 +- 10 files changed, 243 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b62e2b7..41ed41a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,9 +252,11 @@ dependencies = [ "glfw", "glutin", "image2", - "imgui-glfw-rs", + "imgui", "imgui-inspect", "imgui-inspect-derive", + "imgui-opengl-renderer", + "imgui-winit-support", "inline_tweak", "log", "simple-logging", @@ -465,16 +467,6 @@ dependencies = [ "parking_lot", ] -[[package]] -name = "imgui-glfw-rs" -version = "0.4.2" -source = "git+https://github.com/Leinnan/imgui-glfw-rs#9537c6d82f1594b22603a4e729e3943a326c54ac" -dependencies = [ - "glfw", - "imgui", - "imgui-opengl-renderer", -] - [[package]] name = "imgui-inspect" version = "0.5.0" @@ -516,6 +508,16 @@ dependencies = [ "cc", ] +[[package]] +name = "imgui-winit-support" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98171c35263e3eb0dfb66cb876e3efdb788d777c1b613c7d2592303d1276bb5" +dependencies = [ + "imgui", + "winit", +] + [[package]] name = "inline_tweak" version = "1.0.8" diff --git a/Cargo.toml b/Cargo.toml index 762f98e..82af2ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,10 @@ lto = true [dependencies] gl = "0.14.0" -imgui-glfw-rs = { git = "https://github.com/Leinnan/imgui-glfw-rs", optional = true } +imgui="0.4" +imgui-winit-support = {version="0.4.0", optional=true} +imgui-opengl-renderer = {version="0.8", optional = true} +# imgui-glfw-rs = { git = "https://github.com/Leinnan/imgui-glfw-rs", optional = true } glfw = {version="0.40.0", optional = true} cgmath = "0.17.0" imgui-inspect = {version="0.5.0", optional = true} @@ -24,8 +27,8 @@ image2 = { git = "https://github.com/Leinnan/image2-rs", branch="legacy", defaul glutin = "0.24.1" [features] -default = [] -imgui_inspect = ["imgui-inspect-derive", "imgui-inspect", "imgui-glfw-rs"] +default = ["imgui_inspect"] +imgui_inspect = ["imgui-inspect-derive","imgui-opengl-renderer", "imgui-inspect", "imgui-winit-support"] glfw_obsolete = ["glfw"] [profile.dev.package."*"] diff --git a/src/example_client.rs b/src/example_client.rs index 4498521..6014ef9 100644 --- a/src/example_client.rs +++ b/src/example_client.rs @@ -11,7 +11,7 @@ use cgmath::prelude::*; use cgmath::{perspective, vec3, Deg, Matrix4, Point3, Vector3}; #[cfg(feature = "glfw_obsolete")] use glfw; -#[cfg(feature = "imgui_inspect")] +#[cfg(feature = "glfw_obsolete")] use imgui_glfw_rs::glfw; pub struct ExampleClient { @@ -128,8 +128,7 @@ impl Client for ExampleClient { } fn update(&mut self, _engine: &mut Engine) {} - - #[cfg(feature="glfw_obsolete")] + #[cfg(feature = "glfw_obsolete")] fn process_input(&mut self, window: &glfw::Window, delta: f32) { use glfw::{Action, Key}; if window.get_key(Key::W) == Action::Press { @@ -153,8 +152,8 @@ impl Client for ExampleClient { } #[cfg(feature = "imgui_inspect")] - fn debug_draw(&mut self, ui: &imgui_glfw_rs::imgui::Ui) { - use imgui_glfw_rs::imgui::*; + fn debug_draw(&mut self, ui: &imgui::Ui) { + use imgui::*; if let Some(menu_bar) = ui.begin_main_menu_bar() { if let Some(menu) = ui.begin_menu(im_str!("Basic"), true) { if MenuItem::new(im_str!("Show Object info")) diff --git a/src/gaia/camera.rs b/src/gaia/camera.rs index a1ff1f6..24d9f2e 100644 --- a/src/gaia/camera.rs +++ b/src/gaia/camera.rs @@ -6,7 +6,7 @@ use cgmath; use cgmath::prelude::*; use cgmath::vec3; #[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::imgui; +use imgui; #[cfg(feature = "imgui_inspect")] use imgui_inspect_derive::Inspect; diff --git a/src/gaia/client.rs b/src/gaia/client.rs index e0e077e..82cfc68 100644 --- a/src/gaia/client.rs +++ b/src/gaia/client.rs @@ -2,18 +2,18 @@ use crate::gaia::assets_cache::AssetsCache; use crate::gaia::engine::Engine; #[cfg(feature = "glfw_obsolete")] use glfw; -#[cfg(feature = "imgui_inspect")] +#[cfg(feature = "glfw_obsolete")] use imgui_glfw_rs::glfw; pub trait Client { fn load_assets(&mut self, cache: &mut AssetsCache); fn update(&mut self, engine: &mut Engine); - #[cfg(feature="glfw_obsolete")] + #[cfg(feature = "glfw_obsolete")] fn process_input(&mut self, window: &glfw::Window, delta: f32); fn on_mouse_scroll(&mut self, yoffset: f32); fn on_mouse_move(&mut self, x: f32, y: f32); // fn draw(&mut self, engine: &mut Engine) where T: Client; unsafe fn draw(&mut self); #[cfg(feature = "imgui_inspect")] - fn debug_draw(&mut self, ui: &imgui_glfw_rs::imgui::Ui); + fn debug_draw(&mut self, ui: &imgui::Ui); } diff --git a/src/gaia/components.rs b/src/gaia/components.rs index 9885722..c4b43f5 100644 --- a/src/gaia/components.rs +++ b/src/gaia/components.rs @@ -4,7 +4,7 @@ use crate::gaia::model::Model; use crate::gaia::shader::Shader; use cgmath::{vec3, Matrix4, Rad, Vector3}; #[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::imgui; +use imgui; #[cfg(feature = "imgui_inspect")] use imgui_inspect_derive::Inspect; diff --git a/src/gaia/engine.rs b/src/gaia/engine.rs index d816b93..593686b 100644 --- a/src/gaia/engine.rs +++ b/src/gaia/engine.rs @@ -5,58 +5,135 @@ use crate::gaia::client::Client; use crate::gaia::consts; use crate::gaia::framebuffer::FramebufferSystem; use cgmath::Point3; -#[cfg(feature = "glfw_obsolete")] -use glfw; #[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::glfw; +use imgui::Context; #[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::imgui; -#[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::ImguiGLFW; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; use log::{info, trace, warn}; -#[cfg(not(feature="glfw_obsolete"))] +#[cfg(not(feature = "glfw_obsolete"))] pub struct Engine { title: String, - size: (i32,i32), + size: (i32, i32), debug_layer: bool, } -#[cfg(not(feature="glfw_obsolete"))] +#[cfg(not(feature = "glfw_obsolete"))] impl Default for Engine { fn default() -> Self { - Engine{ + Engine { title: String::from("Doppler demo"), size: (1280, 720), - debug_layer: false, + debug_layer: true, } } } -#[cfg(not(feature="glfw_obsolete"))] +#[cfg(not(feature = "glfw_obsolete"))] impl Engine { - pub fn run(&self) { + pub fn run(self) { let event_loop = glutin::event_loop::EventLoop::new(); - let window = glutin::window::WindowBuilder::new().with_title(&self.title) - .with_inner_size(glutin::dpi::LogicalSize::new(self.size.0 as f32, self.size.1 as f32)); + let window = glutin::window::WindowBuilder::new() + .with_title(&self.title) + .with_inner_size(glutin::dpi::PhysicalSize::new( + self.size.0 as f32, + self.size.1 as f32, + )) + .with_resizable(true); let gl_window = glutin::ContextBuilder::new() .build_windowed(window, &event_loop) .unwrap(); let gl_window = unsafe { gl_window.make_current().unwrap() }; + info!( + "Pixel format of the window's GL context: {:?}", + gl_window.get_pixel_format() + ); + gl::load_with(|symbol| gl_window.get_proc_address(symbol)); // configure global opengl state // ----------------------------- unsafe { + gl::Enable(gl::BLEND); + gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); gl::Enable(gl::DEPTH_TEST); + gl::DepthFunc(gl::LESS); + gl::ClearColor(0.1, 0.1, 0.1, 1.0); } + info!("DPI: {}", gl_window.window().scale_factor()); let mut client = ExampleClient::create(); - let mut framebuffer = unsafe { FramebufferSystem::generate(1024, 768) }; - let mut camera = Camera { - position: Point3::new(0.0, 0.0, 3.0), - ..Camera::default() - }; + let mut framebuffer = unsafe { FramebufferSystem::generate(self.size.0, self.size.1) }; + let mut imgui = Context::create(); + { + use imgui::{FontSource, StyleColor}; + let mut style = imgui.style_mut(); + // style.scale_all_sizes(1.5); + style[StyleColor::Text] = [1.0, 1.0, 1.0, 1.0]; + style[StyleColor::TextDisabled] = [0.5, 0.5, 0.5, 1.0]; + style[StyleColor::WindowBg] = [0.13, 0.14, 0.15, 1.0]; + style[StyleColor::ChildBg] = [0.13, 0.14, 0.15, 1.0]; + style[StyleColor::PopupBg] = [0.13, 0.14, 0.15, 1.0]; + style[StyleColor::Border] = [0.43, 0.43, 0.50, 0.50]; + style[StyleColor::BorderShadow] = [0.00, 0.00, 0.00, 0.00]; + style[StyleColor::FrameBg] = [0.25, 0.25, 0.25, 1.00]; + style[StyleColor::FrameBgHovered] = [0.38, 0.38, 0.38, 1.00]; + style[StyleColor::FrameBgActive] = [0.67, 0.67, 0.67, 0.39]; + style[StyleColor::TitleBg] = [0.08, 0.08, 0.09, 1.00]; + style[StyleColor::TitleBgActive] = [0.08, 0.08, 0.09, 1.00]; + style[StyleColor::TitleBgCollapsed] = [0.00, 0.00, 0.00, 0.51]; + style[StyleColor::MenuBarBg] = [0.14, 0.14, 0.14, 1.00]; + style[StyleColor::ScrollbarBg] = [0.02, 0.02, 0.02, 0.53]; + style[StyleColor::ScrollbarGrab] = [0.31, 0.31, 0.31, 1.00]; + style[StyleColor::ScrollbarGrabHovered] = [0.41, 0.41, 0.41, 1.00]; + style[StyleColor::ScrollbarGrabActive] = [0.51, 0.51, 0.51, 1.00]; + style[StyleColor::CheckMark] = [0.11, 0.64, 0.92, 1.00]; + style[StyleColor::SliderGrab] = [0.11, 0.64, 0.92, 1.00]; + style[StyleColor::SliderGrabActive] = [0.08, 0.50, 0.72, 1.00]; + style[StyleColor::Button] = [0.25, 0.25, 0.25, 1.00]; + style[StyleColor::ButtonHovered] = [0.38, 0.38, 0.38, 1.00]; + style[StyleColor::ButtonActive] = [0.67, 0.67, 0.67, 0.39]; + style[StyleColor::Header] = [0.22, 0.22, 0.22, 1.00]; + style[StyleColor::HeaderHovered] = [0.25, 0.25, 0.25, 1.00]; + style[StyleColor::HeaderActive] = [0.67, 0.67, 0.67, 0.39]; + style[StyleColor::Separator] = style[StyleColor::Border]; + style[StyleColor::SeparatorHovered] = [0.41, 0.42, 0.44, 1.00]; + style[StyleColor::SeparatorActive] = [0.26, 0.59, 0.98, 0.95]; + style[StyleColor::ResizeGrip] = [0.00, 0.00, 0.00, 0.00]; + style[StyleColor::ResizeGripHovered] = [0.29, 0.30, 0.31, 0.67]; + style[StyleColor::ResizeGripActive] = [0.26, 0.59, 0.98, 0.95]; + style[StyleColor::Tab] = [0.08, 0.08, 0.09, 0.83]; + style[StyleColor::TabHovered] = [0.33, 0.34, 0.36, 0.83]; + style[StyleColor::TabActive] = [0.23, 0.23, 0.24, 1.00]; + style[StyleColor::TabUnfocused] = [0.08, 0.08, 0.09, 1.00]; + style[StyleColor::TabUnfocusedActive] = [0.13, 0.14, 0.15, 1.00]; + // style[StyleColor::DockingPreview] = [0.26, 0.59, 0.98, 0.70]; + // style[StyleColor::DockingEmptyBg] = [0.20, 0.20, 0.20, 1.00]; + style[StyleColor::PlotLines] = [0.61, 0.61, 0.61, 1.00]; + style[StyleColor::PlotLinesHovered] = [1.00, 0.43, 0.35, 1.00]; + style[StyleColor::PlotHistogram] = [0.90, 0.70, 0.00, 1.00]; + style[StyleColor::PlotHistogramHovered] = [1.00, 0.60, 0.00, 1.00]; + style[StyleColor::TextSelectedBg] = [0.26, 0.59, 0.98, 0.35]; + style[StyleColor::DragDropTarget] = [0.11, 0.64, 0.92, 1.00]; + style[StyleColor::NavHighlight] = [0.26, 0.59, 0.98, 1.00]; + style[StyleColor::NavWindowingHighlight] = [1.00, 1.00, 1.00, 0.70]; + style[StyleColor::NavWindowingDimBg] = [0.80, 0.80, 0.80, 0.20]; + style[StyleColor::ModalWindowDimBg] = [0.80, 0.80, 0.80, 0.35]; + style.grab_rounding = 2.3; + style.frame_rounding = style.grab_rounding; + imgui.fonts().clear(); + imgui.fonts().add_font(&[FontSource::TtfData { + data: include_bytes!("../../resources/FiraSans-SemiBold.ttf"), + size_pixels: 19.0, + config: None, + }]); + info!("Fonts amount int imgui: {}", imgui.fonts().fonts().len()); + } + let mut platform = WinitPlatform::init(&mut imgui); // step 1 + platform.attach_window(imgui.io_mut(), &gl_window.window(), HiDpiMode::Locked(1.0)); // step 2 + let renderer = imgui_opengl_renderer::Renderer::new(&mut imgui, |s| { + gl_window.get_proc_address(s) as _ + }); let mut assets_cache = AssetsCache::default(); client.load_assets(&mut assets_cache); let mut first_mouse = true; @@ -64,41 +141,125 @@ impl Engine { let mut last_y: f32 = consts::SCR_HEIGHT as f32 / 2.0; // timing - let mut delta_time: f32; // time between current frame and last frame + let mut delta_time: f32 = 0.0; // time between current frame and last frame let mut last_frame: f32 = 0.0; + let mut last_frame = std::time::Instant::now(); - - event_loop.run(move |event, _, control_flow| { - use glutin::event::{Event, WindowEvent}; - use glutin::event_loop::ControlFlow; - *control_flow = ControlFlow::Poll; - match event { - Event::LoopDestroyed => return, - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(size) => { - info!("Resizing!"); - unsafe { gl::Viewport(0, 0, size.width as i32, size.height as i32) } - let window_size = (size.width as f32, size.height as f32); - framebuffer = unsafe { FramebufferSystem::generate(size.width as i32, size.height as i32) }; - }, - _ => (), - }, - Event::RedrawRequested(_) => { - unsafe { - framebuffer.clear(); - client.draw(); - framebuffer.draw(); + let mut screensize = self.size; + + event_loop.run(move |event, _, control_flow| { + use glutin::event::{Event, WindowEvent}; + use glutin::event_loop::ControlFlow; + *control_flow = ControlFlow::Poll; + platform.handle_event(imgui.io_mut(), &gl_window.window(), &event); + match event { + Event::NewEvents(_) => { + // other application-specific logic + last_frame = imgui.io_mut().update_delta_time(last_frame); } - gl_window.swap_buffers().unwrap(); - }, - _ => (), - } - }); + Event::MainEventsCleared => { + // other application-specific logic + platform + .prepare_frame(imgui.io_mut(), &gl_window.window()) // step 4 + .expect("Failed to prepare frame"); + gl_window.window().request_redraw(); + } + Event::LoopDestroyed => return, + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::Resized(size) => { + info!("Resizing to {:?}", size); + unsafe { gl::Viewport(0, 0, size.width as i32, size.height as i32) } + screensize = (size.width as i32, size.height as i32); + framebuffer = unsafe { + FramebufferSystem::generate(size.width as i32, size.height as i32) + }; + + platform.attach_window( + imgui.io_mut(), + &gl_window.window(), + HiDpiMode::Locked(1.0), + ); // step 2 + } + _ => (), + }, + Event::RedrawRequested(_) => { + unsafe { + framebuffer.clear(); + client.draw(); + framebuffer.draw(); + } + if self.debug_layer { + imgui.io_mut().display_size = [screensize.0 as f32, screensize.1 as f32]; + let imgui_size = imgui.io().display_size; + let ui = imgui.frame(); + client.debug_draw(&ui); + use imgui::*; + let fps = 1.0 / delta_time; + let size = [250.0, 110.0]; + let offset = 20.0; + Window::new(im_str!("EngineInfo")) + .size(size, Condition::Always) + .position( + [ + imgui_size[0] - size[0] - offset, + imgui_size[1] - size[1] - offset, + ], + Condition::Always, + ) + .no_decoration() + .no_inputs() + .bg_alpha(0.8) + .save_settings(false) + .build(&ui, || { + ui.text("Welcome in doppler world!"); + ui.text(format!("FPS: {:.0}", fps)); + ui.separator(); + ui.text(format!("Mouse position: ({:4.1},{:4.1})", last_x, last_y)); + }); + Window::new(im_str!("Logs")) + .size([670.0, 215.0], Condition::Always) + .bg_alpha(0.8) + .position( + [offset, imgui_size[1] as f32 - 215.0 - offset], + Condition::Always, + ) + .no_decoration() + .no_inputs() + .bg_alpha(0.8) + .save_settings(false) + .build(&ui, || { + use std::fs; + use std::io::prelude::*; + use std::io::BufReader; + let buf = BufReader::new( + fs::File::open("log.log").expect("no such file"), + ); + let lines: Vec = buf + .lines() + .map(|l| l.expect("Could not parse line")) + .collect(); + let mut output = String::new(); + lines.iter().rev().take(10).rev().for_each(|line| { + output.push_str(&line); + output.push('\n'); + }); + + ui.text(output); + }); + platform.prepare_render(&ui, &gl_window.window()); + renderer.render(ui); + // let draw_data = ui.render(); + } + gl_window.swap_buffers().unwrap(); + } + _ => (), + } + }); } } -#[cfg(feature="glfw_obsolete")] +#[cfg(feature = "glfw_obsolete")] pub struct Engine { pub camera: Camera, pub ctx_wrapper: glutin::ContextWrapper, @@ -113,7 +274,7 @@ pub struct Engine { framebuffer: FramebufferSystem, } -#[cfg(feature="glfw_obsolete")] +#[cfg(feature = "glfw_obsolete")] impl Engine { pub fn run(&mut self) { self.client.load_assets(&mut self.assets_cache); @@ -283,7 +444,7 @@ impl Engine { } } -#[cfg(feature="glfw_obsolete")] +#[cfg(feature = "glfw_obsolete")] impl Default for Engine { fn default() -> Self { // // glfw: initialize and configure diff --git a/src/gaia/imgui_helper.rs b/src/gaia/imgui_helper.rs index 0261520..82dea8d 100644 --- a/src/gaia/imgui_helper.rs +++ b/src/gaia/imgui_helper.rs @@ -1,5 +1,5 @@ use cgmath::{Point3, Vector3}; -use imgui_glfw_rs::imgui; +use imgui; use imgui_inspect::InspectArgsDefault; use imgui_inspect::InspectRenderDefault; diff --git a/src/gaia/light.rs b/src/gaia/light.rs index 19a5158..8ac4ae6 100644 --- a/src/gaia/light.rs +++ b/src/gaia/light.rs @@ -3,7 +3,7 @@ use crate::gaia::imgui_helper::*; use crate::gaia::shader::Shader; use cgmath::{perspective, vec3, Deg, Matrix4, Point3, Vector3}; #[cfg(feature = "imgui_inspect")] -use imgui_glfw_rs::imgui; +use imgui; #[cfg(feature = "imgui_inspect")] use imgui_inspect_derive::Inspect; diff --git a/src/main.rs b/src/main.rs index 63591c1..f5d6188 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ extern crate gl; extern crate glutin; #[cfg(feature = "imgui_inspect")] -extern crate imgui_glfw_rs; +extern crate imgui; extern crate log; extern crate simple_logging;