diff --git a/Cargo.toml b/Cargo.toml index c3b138d..70be850 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ exe = [] android = [] [dependencies] -glutin = { path = "./3rdparty/glutin/glutin", optional = true } +#glutin = { path = "./3rdparty/glutin/glutin", optional = true } #winit = { path = "./3rdparty/winit", optional = true, default_features = false, features = ["x11"] } #sdl2 = { path = "./3rdparty/rust-sdl2", optional = true, features = ["unsafe_textures", "bundled", "static-link"] } #sdl2-sys = { path = "./3rdparty/rust-sdl2/sdl2-sys", optional = true, features = ["bundled", "static-link"] } @@ -66,7 +66,7 @@ discord-rich-presence = { version = "0.2", optional = true } downcast = "0.11" encoding_rs = "0.8.33" fern = "0.6.2" -#glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "2dd95f042e6e090d36f577cbea125560dd99bd27", optional = true, default_features = false, features = ["x11"] } +glutin = { version = "0.32.0", optional = true } imgui = { git = "https://github.com/imgui-rs/imgui-rs.git", rev = "67f7f11363e62f09aa0e1288a17800e505860486" } image = { version = "0.24", default-features = false, features = ["png", "bmp"] } itertools = "0.10" diff --git a/src/framework/backend.rs b/src/framework/backend.rs index 76bd9b7..bf1a95b 100644 --- a/src/framework/backend.rs +++ b/src/framework/backend.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::cell::RefCell; use std::rc::Rc; use imgui::DrawData; @@ -82,8 +83,8 @@ pub trait BackendRenderer { /// Set the current clipping rectangle. fn set_clip_rect(&mut self, rect: Option) -> GameResult; - /// Get a mutable reference to the imgui context. - fn imgui(&self) -> GameResult<&mut imgui::Context>; + /// Get a reference to the imgui context. + fn imgui(&self) -> GameResult>>; /// Get an imgui texture id for the specified texture. fn imgui_texture_id(&self, texture: &Box) -> GameResult; diff --git a/src/framework/backend_null.rs b/src/framework/backend_null.rs index 4dcde17..a61572a 100644 --- a/src/framework/backend_null.rs +++ b/src/framework/backend_null.rs @@ -1,6 +1,7 @@ use std::any::Any; use std::cell::RefCell; use std::mem; +use std::rc::Rc; use imgui::{DrawData, TextureId, Ui}; @@ -25,7 +26,7 @@ impl Backend for NullBackend { fn create_event_loop(&self, _ctx: &Context) -> GameResult> { Ok(Box::new(NullEventLoop)) } - + fn as_any(&self) -> &dyn Any { self } @@ -53,10 +54,7 @@ impl BackendEventLoop for NullEventLoop { fn new_renderer(&self) -> GameResult> { let mut imgui = imgui::Context::create(); - imgui.io_mut().display_size = [640.0, 480.0]; - imgui.fonts().build_alpha8_texture(); - - Ok(Box::new(NullRenderer(RefCell::new(imgui)))) + NullRenderer::new(imgui) } fn as_any(&self) -> &dyn Any { @@ -84,12 +82,12 @@ impl BackendTexture for NullTexture { } } -pub struct NullRenderer(RefCell); +pub struct NullRenderer(Rc>); impl NullRenderer { - pub fn new(mut imgui: imgui::Context) -> Self { + pub fn new(mut imgui: imgui::Context) -> GameResult> { let _ = imgui.fonts().build_alpha8_texture(); - NullRenderer(RefCell::new(imgui)) + Ok(Box::new(NullRenderer(Rc::new(RefCell::new(imgui))))) } } @@ -132,8 +130,8 @@ impl BackendRenderer for NullRenderer { Ok(()) } - fn imgui(&self) -> GameResult<&mut imgui::Context> { - unsafe { Ok(&mut *self.0.as_ptr()) } + fn imgui(&self) -> GameResult>> { + Ok(self.0.clone()) } fn imgui_texture_id(&self, _texture: &Box) -> GameResult { diff --git a/src/framework/backend_sdl2.rs b/src/framework/backend_sdl2.rs index a3e7f23..eee1de2 100644 --- a/src/framework/backend_sdl2.rs +++ b/src/framework/backend_sdl2.rs @@ -44,6 +44,8 @@ use crate::game::shared_game_state::WindowMode; use crate::game::Game; use crate::game::GAME_SUSPENDED; +use super::graphics; + pub struct SDL2Backend { context: Sdl, size_hint: (u16, u16), @@ -315,37 +317,39 @@ impl SDL2EventLoop { let gl_context: GLContext = GLContext { gles2_mode: false, platform }; let imgui = Self::create_imgui()?; - OpenGLRenderer::new(gl_context, imgui) } fn try_create_sdl2_renderer(&self) -> GameResult> { let imgui = Self::create_imgui()?; + + fn try_create_sdl2_renderer(&self) -> GameResult> { let mut refs = self.refs.borrow_mut(); let window = std::mem::take(&mut refs.window); refs.window = window.make_canvas()?; + let imgui = Self::create_imgui()?; SDL2Renderer::new(self.refs.clone(), imgui) } } impl BackendEventLoop for SDL2EventLoop { fn run(&mut self, game: &mut Game, ctx: &mut Context) { - let imgui = unsafe { (&*(ctx.renderer.as_ref().unwrap() as *const Box)).imgui().unwrap() }; - let mut imgui_sdl2 = ImguiSdl2::new(imgui, self.refs.deref().borrow().window.window()); + let imgui = graphics::imgui_context(ctx).unwrap(); + let mut imgui_sdl2 = ImguiSdl2::new(&mut imgui.borrow_mut(), self.refs.deref().borrow().window.window()); { let state = game.state.get_mut(); let (width, height) = self.refs.deref().borrow().window.window().size(); ctx.screen_size = (width.max(1) as f32, height.max(1) as f32); - imgui.io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1]; + imgui.borrow_mut().io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1]; let _ = state.handle_resize(ctx); } loop { for event in self.event_pump.poll_iter() { - imgui_sdl2.handle_event(imgui, &event); + imgui_sdl2.handle_event(&mut imgui.borrow_mut(), &event); match event { Event::Quit { .. } => { @@ -377,11 +381,7 @@ impl BackendEventLoop for SDL2EventLoop { let state = game.state.get_mut(); ctx.screen_size = (width.max(1) as f32, height.max(1) as f32); - if let Some(renderer) = &ctx.renderer { - if let Ok(imgui) = renderer.imgui() { - imgui.io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1]; - } - } + imgui.borrow_mut().io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1]; state.handle_resize(ctx).unwrap(); } _ => {} @@ -504,7 +504,7 @@ impl BackendEventLoop for SDL2EventLoop { game.update(ctx).unwrap(); imgui_sdl2.prepare_frame( - imgui.io_mut(), + imgui.borrow_mut().io_mut(), self.refs.deref().borrow().window.window(), &self.event_pump.mouse_state(), ); @@ -879,8 +879,8 @@ impl BackendRenderer for SDL2Renderer { Ok(()) } - fn imgui(&self) -> GameResult<&mut imgui::Context> { - unsafe { Ok(&mut *self.imgui.as_ptr()) } + fn imgui(&self) -> GameResult>> { + Ok(self.imgui.clone()) } fn imgui_texture_id(&self, texture: &Box) -> GameResult { diff --git a/src/framework/graphics.rs b/src/framework/graphics.rs index 97c9a3d..c285f98 100644 --- a/src/framework/graphics.rs +++ b/src/framework/graphics.rs @@ -1,3 +1,6 @@ +use std::cell::RefCell; +use std::rc::Rc; + use crate::common::{Color, Rect}; use crate::framework::backend::{BackendShader, BackendTexture, VertexData}; use crate::framework::context::Context; @@ -130,7 +133,7 @@ pub fn set_clip_rect(ctx: &mut Context, rect: Option) -> GameResult { Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string())) } -pub fn imgui_context(ctx: &Context) -> GameResult<&mut imgui::Context> { +pub fn imgui_context(ctx: &Context) -> GameResult>> { if let Some(renderer) = ctx.renderer.as_ref() { return renderer.imgui(); } diff --git a/src/framework/render_opengl.rs b/src/framework/render_opengl.rs index ae9f5d1..03a6c5a 100644 --- a/src/framework/render_opengl.rs +++ b/src/framework/render_opengl.rs @@ -662,7 +662,7 @@ pub fn load_gl(gl_context: &GLContext) -> Rc { pub struct OpenGLRenderer { refs: GLContext, gl: Rc, - imgui: UnsafeCell, + imgui: Rc>, render_data: RenderData, def_matrix: [[f32; 4]; 4], curr_matrix: [[f32; 4]; 4], @@ -683,7 +683,7 @@ impl OpenGLRenderer { Ok(Box::new(OpenGLRenderer { refs, gl, - imgui: UnsafeCell::new(imgui), + imgui: Rc::new(RefCell::new(imgui)), render_data, def_matrix: [[0.0; 4]; 4], curr_matrix: [[0.0; 4]; 4], @@ -1059,8 +1059,8 @@ impl BackendRenderer for OpenGLRenderer { Ok(()) } - fn imgui(&self) -> GameResult<&mut imgui::Context> { - unsafe { Ok(&mut *self.imgui.get()) } + fn imgui(&self) -> GameResult>> { + Ok(self.imgui.clone()) } fn imgui_texture_id(&self, texture: &Box) -> GameResult { @@ -1090,8 +1090,8 @@ impl BackendRenderer for OpenGLRenderer { gl.gl.Enable(gl::SCISSOR_TEST); let imgui = self.imgui()?; - let [width, height] = imgui.io().display_size; - let [scale_w, scale_h] = imgui.io().display_framebuffer_scale; + let [width, height] = imgui.borrow().io().display_size; + let [scale_w, scale_h] = imgui.borrow().io().display_framebuffer_scale; let fb_width = width * scale_w; let fb_height = height * scale_h; diff --git a/src/framework/ui.rs b/src/framework/ui.rs index 6040f5b..7027dcb 100644 --- a/src/framework/ui.rs +++ b/src/framework/ui.rs @@ -1,7 +1,7 @@ use std::time::Instant; -use imgui::{FontConfig, FontSource}; use imgui::sys::*; +use imgui::{FontConfig, FontSource}; use crate::framework::context::Context; use crate::framework::error::GameResult; @@ -108,19 +108,20 @@ impl UI { } pub fn draw(&mut self, state: &mut SharedGameState, ctx: &mut Context, scene: &mut Box) -> GameResult { - let ctx2 = unsafe { &mut *(ctx as *const Context as *mut Context) }; let imgui = imgui_context(ctx)?; + let mut imgui = imgui.borrow_mut(); + let now = Instant::now(); imgui.io_mut().update_delta_time(now - self.last_frame); self.last_frame = now; let mut ui = imgui.new_frame(); - scene.imgui_draw(&mut self.components, state, ctx2, &mut ui)?; + scene.imgui_draw(&mut self.components, state, ctx, &mut ui)?; - prepare_imgui(ctx2, &ui); + prepare_imgui(ctx, &ui); let draw_data = imgui.render(); - render_imgui(ctx2, draw_data)?; + render_imgui(ctx, draw_data)?; Ok(()) }