diff --git a/src/components.rs b/src/components.rs index a344949..65db69e 100644 --- a/src/components.rs +++ b/src/components.rs @@ -8,6 +8,11 @@ use cgmath::Deg; // a component is any type that is 'static, sized, send and sync + +pub struct ImguiWindow<'a> { + pub window: imgui::Window<'a>, +} + #[derive(Clone, Copy, Debug, PartialEq)] pub struct LoopState { pub delta_time: Duration, diff --git a/src/extended_winit_imgui_support.rs b/src/imgui_supp/extended_winit_imgui_support.rs similarity index 96% rename from src/extended_winit_imgui_support.rs rename to src/imgui_supp/extended_winit_imgui_support.rs index 76aae5e..74fb9a1 100644 --- a/src/extended_winit_imgui_support.rs +++ b/src/imgui_supp/extended_winit_imgui_support.rs @@ -1,4 +1,4 @@ -//! This crate provides a winit-based backend platform for imgui-rs. +//! This crate provides a winit-based backend platform for imgui_supp-rs. //! //! A backend platform handles window/input device events and manages their //! state. @@ -17,7 +17,7 @@ //! //! ```rust,no_run,ignore //! # // TODO: Remove ignore when only one winit version is used -//! use imgui::Context; +//! use imgui_supp::Context; //! use imgui_winit_support::{HiDpiMode, WinitPlatform}; //! use std::time::Instant; //! use winit::event::{Event, WindowEvent}; @@ -27,11 +27,11 @@ //! let mut event_loop = EventLoop::new(); //! let mut window = Window::new(&event_loop).unwrap(); //! -//! let mut imgui = Context::create(); -//! // configure imgui-rs Context if necessary +//! let mut imgui_supp = Context::create(); +//! // configure imgui_supp-rs Context if necessary //! -//! let mut platform = WinitPlatform::init(&mut imgui); // step 1 -//! platform.attach_window(imgui.io_mut(), &window, HiDpiMode::Default); // step 2 +//! let mut platform = WinitPlatform::init(&mut imgui_supp); // step 1 +//! platform.attach_window(imgui_supp.io_mut(), &window, HiDpiMode::Default); // step 2 //! //! let mut last_frame = Instant::now(); //! let mut run = true; @@ -39,16 +39,16 @@ //! match event { //! Event::NewEvents(_) => { //! // other application-specific logic -//! last_frame = imgui.io_mut().update_delta_time(last_frame); +//! last_frame = imgui_supp.io_mut().update_delta_time(last_frame); //! }, //! Event::MainEventsCleared => { //! // other application-specific logic -//! platform.prepare_frame(imgui.io_mut(), &window) // step 4 +//! platform.prepare_frame(imgui_supp.io_mut(), &window) // step 4 //! .expect("Failed to prepare frame"); //! window.request_redraw(); //! } //! Event::RedrawRequested(_) => { -//! let ui = imgui.frame(); +//! let ui = imgui_supp.frame(); //! // application-specific rendering *under the UI* //! //! // construct the UI @@ -65,7 +65,7 @@ //! } //! // other application-specific event handling //! event => { -//! platform.handle_event(imgui.io_mut(), &window, &event); // step 3 +//! platform.handle_event(imgui_supp.io_mut(), &window, &event); // step 3 //! // other application-specific event handling //! } //! } @@ -107,7 +107,7 @@ //! your `Cargo.toml`: //! //! ```toml -//! [dependencies.imgui-winit-support] +//! [dependencies.imgui_supp-winit-support] //! version = "0.6" //! features = ["winit-$YOUR_VERSION_HERE"] //! default-features = false @@ -238,7 +238,7 @@ fn check_multiple_winits() { // ensure atomicity. let _ = writeln!( err, - "Warning (imgui-winit-support): More than one `winit-*` version feature is enabled \ + "Warning (imgui_supp-winit-support): More than one `winit-*` version feature is enabled \ (this likely indicates misconfiguration, see documentation for details)." ); let feats = [ @@ -373,10 +373,10 @@ enum ActiveHiDpiMode { /// DPI factor handling mode. /// -/// Applications that use imgui-rs might want to customize the used DPI factor and not use +/// Applications that use imgui_supp-rs might want to customize the used DPI factor and not use /// directly the value coming from winit. /// -/// **Note: if you use a mode other than default and the DPI factor is adjusted, winit and imgui-rs +/// **Note: if you use a mode other than default and the DPI factor is adjusted, winit and imgui_supp-rs /// will use different logical coordinates, so be careful if you pass around logical size or /// position values.** #[derive(Copy, Clone, Debug, PartialEq)] @@ -405,9 +405,9 @@ impl HiDpiMode { } impl WinitPlatform { - /// Initializes a winit platform instance and configures imgui. + /// Initializes a winit platform instance and configures imgui_supp. /// - /// This function configures imgui-rs in the following ways: + /// This function configures imgui_supp-rs in the following ways: /// /// * backend flags are updated /// * keys are configured @@ -441,7 +441,7 @@ impl WinitPlatform { io[Key::Y] = VirtualKeyCode::Y as _; io[Key::Z] = VirtualKeyCode::Z as _; imgui.set_platform_name(Some(ImString::from(format!( - "imgui-winit-support {}", + "imgui_supp-winit-support {}", env!("CARGO_PKG_VERSION") )))); WinitPlatform { @@ -453,7 +453,7 @@ impl WinitPlatform { } /// Attaches the platform instance to a winit window. /// - /// This function configures imgui-rs in the following ways: + /// This function configures imgui_supp-rs in the following ways: /// /// * framebuffer scale (= DPI factor) is set /// * display size is set @@ -478,7 +478,7 @@ impl WinitPlatform { } /// Attaches the platform instance to a winit window. /// - /// This function configures imgui-rs in the following ways: + /// This function configures imgui_supp-rs in the following ways: /// /// * framebuffer scale (= DPI factor) is set /// * display size is set @@ -506,7 +506,7 @@ impl WinitPlatform { /// Scales a logical size coming from winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(all( not(any( feature = "winit-24", @@ -527,7 +527,7 @@ impl WinitPlatform { /// Scales a logical size coming from winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(any( feature = "winit-20", feature = "winit-22", @@ -549,7 +549,7 @@ impl WinitPlatform { /// Scales a logical position coming from winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(all( not(any( feature = "winit-24", @@ -574,7 +574,7 @@ impl WinitPlatform { /// Scales a logical position coming from winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(any( feature = "winit-20", feature = "winit-22", @@ -596,7 +596,7 @@ impl WinitPlatform { /// Scales a logical position for winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(all( not(any( feature = "winit-24", @@ -621,7 +621,7 @@ impl WinitPlatform { /// Scales a logical position for winit using the current DPI mode. /// /// This utility function is useful if you are using a DPI mode other than default, and want - /// your application to use the same logical coordinates as imgui-rs. + /// your application to use the same logical coordinates as imgui_supp-rs. #[cfg(any( feature = "winit-20", feature = "winit-22", @@ -722,7 +722,7 @@ impl WinitPlatform { // We need to track modifiers separately because some system like macOS, will // 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_supp widgets! Event::DeviceEvent { event: DeviceEvent::ModifiersChanged(modifiers), .. @@ -751,7 +751,7 @@ impl WinitPlatform { } if window_id == window.id() => { // We need to track modifiers separately because some system like macOS, will // 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_supp widgets! if let OwnedWindowEvent::ModifiersChanged(modifiers) = event { io.key_shift = modifiers.shift(); io.key_ctrl = modifiers.ctrl(); @@ -1084,10 +1084,10 @@ impl WinitPlatform { } /// Frame preparation callback. /// - /// Call this before calling the imgui-rs context `frame` function. + /// Call this before calling the imgui_supp-rs context `frame` function. /// This function performs the following actions: /// - /// * mouse cursor is repositioned (if requested by imgui-rs) + /// * mouse cursor is repositioned (if requested by imgui_supp-rs) #[cfg(all( not(any( feature = "winit-24", @@ -1111,10 +1111,10 @@ impl WinitPlatform { } /// Frame preparation callback. /// - /// Call this before calling the imgui-rs context `frame` function. + /// Call this before calling the imgui_supp-rs context `frame` function. /// This function performs the following actions: /// - /// * mouse cursor is repositioned (if requested by imgui-rs) + /// * mouse cursor is repositioned (if requested by imgui_supp-rs) #[cfg(any( feature = "winit-20", feature = "winit-22", @@ -1142,10 +1142,10 @@ impl WinitPlatform { /// Render preparation callback. /// - /// Call this before calling the imgui-rs UI `render_with`/`render` function. + /// Call this before calling the imgui_supp-rs UI `render_with`/`render` function. /// This function performs the following actions: /// - /// * mouse cursor is changed and/or hidden (if requested by imgui-rs) + /// * mouse cursor is changed and/or hidden (if requested by imgui_supp-rs) pub fn prepare_render(&mut self, ui: &Ui, window: &Window) { let io = ui.io(); if !io diff --git a/src/imgui_supp/imgui_support.rs b/src/imgui_supp/imgui_support.rs new file mode 100644 index 0000000..1470dfc --- /dev/null +++ b/src/imgui_supp/imgui_support.rs @@ -0,0 +1,12 @@ +use crate::imgui_supp::extended_winit_imgui_support::WinitPlatform; + + +pub struct ImguiContext { + pub context: imgui::Context, +} +unsafe impl Send for ImguiContext {} + +pub struct ImguiPlatform { + pub platform: WinitPlatform, +} +unsafe impl Send for ImguiPlatform {} \ No newline at end of file diff --git a/src/imgui_supp/mod.rs b/src/imgui_supp/mod.rs new file mode 100644 index 0000000..fe2c0ce --- /dev/null +++ b/src/imgui_supp/mod.rs @@ -0,0 +1,2 @@ +pub mod extended_winit_imgui_support; +pub mod imgui_support; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 3fe39eb..d228e3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate imgui_wgpu; extern crate tobj; extern crate winit_24; +use std::borrow::Borrow; use std::f32::consts::PI; use std::rc::Rc; use std::sync::{Arc, Mutex}; @@ -15,10 +16,13 @@ use cgmath::{ }; use futures::executor::block_on; use futures::task::LocalSpawn; -use gilrs::{Gamepad, Gilrs}; use gilrs::Event as GilEvent; +use gilrs::{Gamepad, Gilrs}; +use imgui::FontSource; +use imgui::__core::convert::TryInto; use imgui::*; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; +use legion::systems::{SyncResources, UnsafeResources}; use legion::*; use rapier3d::counters::Timer; use rapier3d::dynamics::{ @@ -30,32 +34,30 @@ use rapier3d::na::{Isometry, Isometry3, Vector, Vector3}; use rapier3d::pipeline::PhysicsPipeline; use wgpu::{BindGroup, Buffer, TextureView}; use wgpu_subscriber; +use winit_24::event::DeviceEvent::MouseMotion; +use winit_24::platform::unix::x11::ffi::Time; +use winit_24::window::Window; use winit_24::{ event::{self, WindowEvent}, event_loop::{ControlFlow, EventLoop}, }; -use winit_24::event::DeviceEvent::MouseMotion; -use winit_24::platform::unix::x11::ffi::Time; -use winit_24::window::Window; use crate::camera::{Camera, CameraController}; -use crate::components::{Collider, Color, LoopState, Physics, Position}; +use crate::components::{Collider, Color, ImguiWindow, LoopState, Physics, Position}; +use crate::imgui_supp::extended_winit_imgui_support; +use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::owned_event::{OwnedEvent, OwnedEventExtension}; use crate::physics::PhysicsState; use crate::render::Renderer; -use legion::systems::{UnsafeResources, SyncResources}; -use std::borrow::Borrow; -use imgui::__core::convert::TryInto; -use crate::extended_winit_imgui_support::WinitPlatform; mod camera; mod components; mod geometry; +mod imgui_supp; mod light; mod owned_event; mod physics; mod render; -mod extended_winit_imgui_support; /* @@ -75,12 +77,10 @@ legion ECS https://github.com/amethyst/legion -mvp: - ECS animation render 3d (good!) - input/io + input/io (yep!) collision / physics (yep!) entities & behaviours (got the entities!) @@ -88,20 +88,18 @@ ECS //log::info!(""); +// ImGUI works on more or less a global state. which is MegaLame +static mut CURRENT_UI: Option> = None; +pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> { CURRENT_UI.as_ref() } -pub struct ImguiContext { - pub context: imgui::Context, -} -unsafe impl Send for ImguiContext {} - -pub struct ImguiPlatform { - pub platform: WinitPlatform, -} -unsafe impl Send for ImguiPlatform {} fn main() { let mut world = World::default(); + let mut imgui_prepare_schedule = Schedule::builder() + .add_system(render::imgui_prepare_system()) + .build(); + let mut render_schedule = Schedule::builder() .add_system(render::render_test_system()) .build(); @@ -135,23 +133,24 @@ fn main() { extended_winit_imgui_support::HiDpiMode::Default, ); - // imgui rendering context + // imgui_supp rendering context let mut imgui_context = ImguiContext { context: imgui_context, }; - let mut imgui_platform = ImguiPlatform { - platform: platform, - }; + let mut imgui_platform = ImguiPlatform { platform: platform }; let font_size = 20.0 as f32; imgui_context.context.io_mut().font_global_scale = 1.0 as f32; - imgui_context.context.fonts().add_font(&[FontSource::DefaultFontData { - config: Some(imgui::FontConfig { - oversample_h: 1, - pixel_snap_h: true, - size_pixels: font_size, - ..Default::default() - }), - }]); + imgui_context + .context + .fonts() + .add_font(&[FontSource::DefaultFontData { + config: Some(imgui::FontConfig { + oversample_h: 1, + pixel_snap_h: true, + size_pixels: font_size, + ..Default::default() + }), + }]); imgui_context.context.set_ini_filename(None); // The renderer @@ -236,13 +235,21 @@ fn main() { *control_flow = ControlFlow::Poll; match event { event::Event::NewEvents(cause) => { + + } + + // This is the big boy section of the event loop + // We : dispatch events and clear the queue, query the loops + // time data and prep the dt data. Loop the dt locked + // conditionally, and run the fps locked renderer + event::Event::MainEventsCleared => { event_schedule.execute(&mut world, &mut resources); + imgui_prepare_schedule.execute(&mut world, &mut resources); resources .get_mut::>>() .unwrap() .clear(); - } - event::Event::MainEventsCleared => { + let (step_size, elapsed_time) = { // deltatime since last frame let loop_state = resources.get::().unwrap(); @@ -287,7 +294,8 @@ fn main() { } => *control_flow = ControlFlow::Exit, event::Event::RedrawRequested(_) => { // Call the render system - render_schedule.execute(&mut world, &mut resources); +// imgui_prepare_schedule.execute(&mut world, &mut resources); +// render_schedule.execute(&mut world, &mut resources); } _ => {} } @@ -299,8 +307,9 @@ fn main() { }); } - pub fn entity_loading(world: &mut World, renderer: &mut Renderer) { + + let monkey_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj"); let camera_ent: Entity = world.push(( diff --git a/src/owned_event.rs b/src/owned_event.rs index 10f83f1..725bf58 100644 --- a/src/owned_event.rs +++ b/src/owned_event.rs @@ -10,10 +10,10 @@ use winit_24::window::{Theme, WindowId, Window}; use crate::camera::{Camera, CameraController}; use crate::owned_event::OwnedWindowEvent::MouseWheel; -use crate::{ImguiPlatform, ImguiContext}; use std::sync::{Mutex, Arc}; use std::cmp::Ordering; use imgui::Io; +use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; #[derive(Clone)] pub enum OwnedUIEvent { @@ -297,6 +297,7 @@ pub fn event_dispatch( } _ => {} } + let mut imgui_context = &mut imgui_context.lock().unwrap().context; let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform; diff --git a/src/render.rs b/src/render.rs index a126718..ae54d59 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,4 +1,7 @@ +use std::cell::RefCell; use std::sync::{Arc, Mutex}; +use std::thread::current; +use std::time::Duration; use std::{iter, num::NonZeroU32, ops::Range, rc::Rc}; use bytemuck::__core::mem; @@ -8,6 +11,9 @@ use cgmath::{ Transform, Vector3, }; use futures::executor::LocalPool; +use imgui::sys::ImGuiContext; +use imgui::*; +use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; use legion::world::SubWorld; use legion::*; use rapier3d::parry::motion::RigidMotionComposition; @@ -23,14 +29,10 @@ use winit_24::window::Window; use crate::camera::{Camera, CameraController}; use crate::components::{Color, Mesh, Position, RangeCopy}; +use crate::current_ui; use crate::geometry::{import_mesh, vertex, Vertex}; +use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::light::{DirectionalLight, LightRaw}; -use imgui::*; -use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; -use std::cell::RefCell; -use imgui::sys::ImGuiContext; -use crate::{ImguiContext, ImguiPlatform}; -use std::time::Duration; #[cfg_attr(rustfmt, rustfmt_skip)] #[allow(unused)] @@ -79,6 +81,27 @@ pub struct Pass { uniform_buf: wgpu::Buffer, } +#[system] +#[write_component(Camera)] +pub fn imgui_prepare( + world: &mut SubWorld, + #[resource] winit_window: &mut Window, + #[resource] imgui_context: &mut Arc>, + #[resource] imgui_platform: &mut Arc>, +) { + let mut imgui_context = &mut imgui_context.lock().unwrap().context; + let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform; + + //imgui_state.context.io_mut().update_delta_time(Duration::new(0,160)); + imgui_platform + .prepare_frame(imgui_context.io_mut(), &winit_window) + .expect("Failed to prepare frame"); + + // get the frame and build a ui window + unsafe { crate::CURRENT_UI = Some(std::mem::transmute(imgui_context.frame())) } + + +} #[system] #[write_component(Camera)] #[write_component(Position)] @@ -93,7 +116,6 @@ pub fn render_test( #[resource] imgui_context: &mut Arc>, #[resource] imgui_platform: &mut Arc>, ) { - let mut encoder = renderer .device .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); @@ -101,9 +123,6 @@ pub fn render_test( let frame = renderer.get_current_frame(); - - - // Update the camera uniform buffers, need to make it support selection of // cameras let mut query = <(&mut Camera)>::query(); @@ -118,7 +137,6 @@ pub fn render_test( } let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); - let mut mesh_stack = Vec::new(); // Update the entity uniforms @@ -244,17 +262,12 @@ pub fn render_test( encoder.pop_debug_group(); { - let mut imgui_context = &mut imgui_context.lock().unwrap().context; let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform; //imgui_state.context.io_mut().update_delta_time(Duration::new(0,160)); - imgui_platform - .prepare_frame(imgui_context.io_mut(), &winit_window) - .expect("Failed to prepare frame"); + let ui = unsafe { crate::current_ui().unwrap() }; - // get the frame and build a ui window - let ui = imgui_context.frame(); let window = imgui::Window::new(im_str!("Hello too")); window .size([400.0, 100.0], Condition::FirstUseEver) @@ -263,8 +276,7 @@ pub fn render_test( ui.text(im_str!("Frametime: {:?}", 10.0)); }); - - //ui.show_demo_window(&mut demo_open); + // ui.show_demo_window(&mut true); imgui_platform.prepare_render(&ui, &winit_window); let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { @@ -279,16 +291,23 @@ pub fn render_test( }], depth_stencil_attachment: None, }); - renderer.imgui_renderer - .render(ui.render(), &renderer.queue, &renderer.device, &mut rpass) + + // We gotta do some jank shit here and manually pull the draw data from the UI + let draw_data = unsafe { + crate::CURRENT_UI = None; // This is where the drop() occurs + imgui::sys::igRender(); + &*(imgui::sys::igGetDrawData() as *mut imgui::DrawData) + }; + + renderer + .imgui_renderer + .render(draw_data, &renderer.queue, &renderer.device, &mut rpass) .expect("Rendering failed"); } - renderer.queue.submit(iter::once(encoder.finish())); } - pub struct Renderer { swapchain: SwapChain, swapchain_description: SwapChainDescriptor, @@ -314,7 +333,6 @@ pub struct Renderer { camera_projection: Matrix4, imgui_renderer: ImguiRenderer, - } impl Renderer { @@ -456,7 +474,6 @@ impl Renderer { } pub fn init(window: &Window, imgui_context: &mut ImguiContext) -> Renderer { - // Grab the GPU instance, and query its features let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); let (size, surface) = unsafe { @@ -631,9 +648,7 @@ impl Renderer { slope_scale: 2.0, clamp: 0.0, }, - clamp_depth: device.features().contains( - wgpu::Features::DEPTH_CLAMPING - ), + clamp_depth: device.features().contains(wgpu::Features::DEPTH_CLAMPING), }), multisample: wgpu::MultisampleState::default(), }); @@ -867,14 +882,13 @@ impl Renderer { label: Some("Depth Texture"), }); - // Imgui renderer let renderer_config = ImguiRendererConfig { texture_format: sc_desc.format, ..Default::default() }; - let mut imgui_renderer = ImguiRenderer::new(&mut imgui_context.context, &device, &queue, renderer_config); - + let mut imgui_renderer = + ImguiRenderer::new(&mut imgui_context.context, &device, &queue, renderer_config); Renderer { swapchain: swap_chain, @@ -893,7 +907,7 @@ impl Renderer { instance: Arc::new(instance), views_given: 0, camera_projection: mx_projection, - imgui_renderer + imgui_renderer, } }