From 191a346545c76f944ac06dcf85d7ab15905a4f68 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:07:45 -0400 Subject: [PATCH 01/12] init significant changes --- imgui/src/context.rs | 23 +++--- imgui/src/input/mouse.rs | 54 ++++++------- imgui/src/lib.rs | 53 ++++++++----- imgui/src/stacks.rs | 166 ++++++++++++++++++++++++++------------- imgui/src/string.rs | 10 +-- imgui/src/utils.rs | 5 +- imgui/src/widget/drag.rs | 4 +- 7 files changed, 195 insertions(+), 120 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index 592ed88..a42aed6 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -512,31 +512,36 @@ impl Context { }, } } + + /// Starts a new frame. + #[deprecated(since = "0.9.0", note = "use `new_frame` instead")] + pub fn frame(&mut self) -> Ui<'_> { + self.new_frame() + } + /// Starts a new frame and returns an `Ui` instance for constructing a user interface. /// /// # Panics /// - /// Panics if the context uses a shared font atlas that is already borrowed + /// Panics if the context uses a shared font atlas that is already borrowed. + /// Do not attempt to borrow the context afterwards, if you are using a shared font atlas. #[doc(alias = "NewFame")] - pub fn frame(&mut self) -> Ui<'_> { + pub fn new_frame(&mut self) -> Ui<'_> { // Clear default font if it no longer exists. This could be an error in the future let default_font = self.io().font_default; if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() { self.io_mut().font_default = ptr::null_mut(); } // NewFrame/Render/EndFrame mutate the font atlas so we need exclusive access to it - let font_atlas = self - .shared_font_atlas - .as_ref() - .map(|font_atlas| font_atlas.borrow_mut()); + if let Some(font_atlas) = self.shared_font_atlas.as_ref() { + assert!(font_atlas.try_borrow_mut().is_ok()); + } // TODO: precondition checks unsafe { sys::igNewFrame(); } Ui { - ctx: self, - font_atlas, - buffer: crate::UiBuffer::new(1024).into(), + phantom_data: std::marker::PhantomData, } } } diff --git a/imgui/src/input/mouse.rs b/imgui/src/input/mouse.rs index 7aa66ab..218b56c 100644 --- a/imgui/src/input/mouse.rs +++ b/imgui/src/input/mouse.rs @@ -237,7 +237,7 @@ fn test_mouse_down_clicked_released() { let (_guard, mut ctx) = crate::test::test_ctx_initialized(); { ctx.io_mut().mouse_down = [false; 5]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_down(button)); assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); @@ -245,14 +245,14 @@ fn test_mouse_down_clicked_released() { } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_down(button)); assert!(ui.is_any_mouse_down()); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_released(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_down(button)); assert!(ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); @@ -260,14 +260,14 @@ fn test_mouse_down_clicked_released() { } { ctx.io_mut()[button] = false; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_down(button)); assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); assert!(ui.is_mouse_released(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_down(button)); assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); @@ -287,42 +287,42 @@ fn test_mouse_double_click() { { // Pass one second of time ctx.io_mut().delta_time = 1.0; - let _ = ctx.frame(); + let _ = ctx.new_frame(); } // Fast clicks ctx.io_mut().delta_time = 1.0 / 60.0; for &button in MouseButton::VARIANTS.iter() { { ctx.io_mut().mouse_down = [false; 5]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = false; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(ui.is_mouse_double_clicked(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } @@ -332,35 +332,35 @@ fn test_mouse_double_click() { for &button in MouseButton::VARIANTS.iter() { { ctx.io_mut().mouse_down = [false; 5]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = false; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } { - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); } @@ -370,7 +370,7 @@ fn test_mouse_double_click() { #[test] fn test_set_get_mouse_cursor() { let (_guard, mut ctx) = crate::test::test_ctx_initialized(); - let ui = ctx.frame(); + let ui = ctx.new_frame(); ui.set_mouse_cursor(None); assert_eq!(None, ui.mouse_cursor()); ui.set_mouse_cursor(Some(MouseCursor::Hand)); @@ -384,7 +384,7 @@ fn test_mouse_drags() { { ctx.io_mut().mouse_pos = [0.0, 0.0]; ctx.io_mut().mouse_down = [false; 5]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_dragging(button)); assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]); @@ -395,7 +395,7 @@ fn test_mouse_drags() { } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_dragging(button)); assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]); @@ -406,7 +406,7 @@ fn test_mouse_drags() { } { ctx.io_mut().mouse_pos = [0.0, 100.0]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_dragging(button)); assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 100.0]); @@ -417,7 +417,7 @@ fn test_mouse_drags() { } { ctx.io_mut().mouse_pos = [0.0, 200.0]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_dragging(button)); assert!(ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 200.0]); @@ -429,7 +429,7 @@ fn test_mouse_drags() { { ctx.io_mut().mouse_pos = [10.0, 10.0]; ctx.io_mut()[button] = false; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_dragging(button)); assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [10.0, 10.0]); @@ -440,7 +440,7 @@ fn test_mouse_drags() { } { ctx.io_mut()[button] = true; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(!ui.is_mouse_dragging(button)); assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]); @@ -451,7 +451,7 @@ fn test_mouse_drags() { } { ctx.io_mut().mouse_pos = [180.0, 180.0]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_dragging(button)); assert!(ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [170.0, 170.0]); @@ -470,7 +470,7 @@ fn test_mouse_drags() { } { ctx.io_mut().mouse_pos = [200.0, 200.0]; - let ui = ctx.frame(); + let ui = ctx.new_frame(); assert!(ui.is_mouse_dragging(button)); assert!(ui.is_mouse_dragging_with_threshold(button, 200.0)); assert_eq!(ui.mouse_drag_delta_with_button(button), [20.0, 20.0]); diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 7bfca42..05fe3f2 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -4,6 +4,7 @@ pub extern crate imgui_sys as sys; +use std::cell; use std::os::raw::{c_char, c_void}; pub use self::clipboard::*; @@ -118,17 +119,37 @@ impl Context { /// A temporary reference for building the user interface for one frame #[derive(Debug)] pub struct Ui<'ui> { - ctx: &'ui Context, - font_atlas: Option>, - // imgui isn't mutli-threaded -- so no one will ever access twice. - buffer: std::cell::UnsafeCell, + phantom_data: std::marker::PhantomData<&'ui Context>, } +/// This is our internal buffer that we use for the Ui object. +/// +/// We edit this buffer +static mut BUFFER: cell::UnsafeCell = + cell::UnsafeCell::new(string::UiBuffer::new(100)); + impl<'ui> Ui<'ui> { + /// This provides access to the backing scratch buffer that we use to write + /// strings, along with null-terminators, before we pass normal Rust strs to + /// Dear ImGui. + /// + /// This is given as a get-out-of-jail free card if you need to handle the buffer, + /// or, for example, resize it for some reason. Generally, you should never need this. + /// + /// ## Safety + /// + /// This uses a **static mut** and we assume it will *never* be passed between threads. + /// Do not pass the raw pointer you get between threads at all -- Dear ImGui is single-threaded. + /// We otherwise make no assumptions about the size or keep state in this buffer between calls, + /// so editing the `UiBuffer` is fine. + pub unsafe fn scratch_buffer(&self) -> &cell::UnsafeCell { + &BUFFER + } + /// Internal method to push a single text to our scratch buffer. fn scratch_txt(&self, txt: impl AsRef) -> *const sys::cty::c_char { unsafe { - let handle = &mut *self.buffer.get(); + let handle = &mut *BUFFER.get(); handle.scratch_txt(txt) } } @@ -136,7 +157,7 @@ impl<'ui> Ui<'ui> { /// Internal method to push an option text to our scratch buffer. fn scratch_txt_opt(&self, txt: Option>) -> *const sys::cty::c_char { unsafe { - let handle = &mut *self.buffer.get(); + let handle = &mut *BUFFER.get(); handle.scratch_txt_opt(txt) } } @@ -147,7 +168,7 @@ impl<'ui> Ui<'ui> { txt_1: impl AsRef, ) -> (*const sys::cty::c_char, *const sys::cty::c_char) { unsafe { - let handle = &mut *self.buffer.get(); + let handle = &mut *BUFFER.get(); handle.scratch_txt_two(txt_0, txt_1) } } @@ -158,7 +179,7 @@ impl<'ui> Ui<'ui> { txt_1: Option>, ) -> (*const sys::cty::c_char, *const sys::cty::c_char) { unsafe { - let handle = &mut *self.buffer.get(); + let handle = &mut *BUFFER.get(); handle.scratch_txt_with_opt(txt_0, txt_1) } } @@ -169,19 +190,13 @@ impl<'ui> Ui<'ui> { unsafe { &*(sys::igGetIO() as *const Io) } } - /// Returns an immutable reference to the font atlas - pub fn fonts(&self) -> FontAtlasRef<'_> { - match self.font_atlas { - Some(ref font_atlas) => FontAtlasRef::Shared(font_atlas), - None => unsafe { - let fonts = &*(self.io().fonts as *const FontAtlas); - FontAtlasRef::Owned(fonts) - }, - } + /// Returns an immutable reference to the font atlas. + pub fn fonts(&self) -> &FontAtlas { + unsafe { &*(self.io().fonts as *const FontAtlas) } } /// Returns a clone of the user interface style pub fn clone_style(&self) -> Style { - *self.ctx.style() + unsafe { *self.style() } } /// Renders the frame and returns a reference to the resulting draw data #[doc(alias = "Render", alias = "GetDrawData")] @@ -614,7 +629,7 @@ impl<'ui> Ui<'ui> { height_in_items: i32, ) -> bool { let (label_ptr, items_inner) = unsafe { - let handle = &mut *self.buffer.get(); + let handle = &mut *self.scratch_buffer().get(); handle.refresh_buffer(); let label_ptr = handle.push(label); diff --git a/imgui/src/stacks.rs b/imgui/src/stacks.rs index 94fad58..44e9632 100644 --- a/imgui/src/stacks.rs +++ b/imgui/src/stacks.rs @@ -1,14 +1,11 @@ -use std::mem; -use std::os::raw::{c_char, c_void}; -use std::ptr; - -use crate::context::Context; use crate::fonts::atlas::FontId; use crate::internal::RawCast; use crate::math::MintVec4; use crate::style::{StyleColor, StyleVar}; use crate::sys; use crate::{Id, Ui}; +use std::mem; +use std::os::raw::{c_char, c_void}; /// # Parameter stacks (shared) impl<'ui> Ui<'ui> { @@ -190,9 +187,9 @@ impl<'ui> Ui<'ui> { /// - `< 0.0`: `item_width` pixels relative to the right of window (-1.0 always aligns width to /// the right side) #[doc(alias = "PushItemWith")] - pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken { + pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken<'_> { unsafe { sys::igPushItemWidth(item_width) }; - ItemWidthStackToken { _ctx: self.ctx } + ItemWidthStackToken::new(self) } /// Sets the width of the next item. /// @@ -220,7 +217,7 @@ impl<'ui> Ui<'ui> { /// /// Returns a `TextWrapPosStackToken` that may be popped by calling `.pop()` #[doc(alias = "PushTextWrapPos")] - pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken { + pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken<'_> { self.push_text_wrap_pos_with_pos(0.0) } @@ -232,25 +229,58 @@ impl<'ui> Ui<'ui> { /// - `= 0.0`: wrap to end of window (or column) /// - `< 0.0`: no wrapping #[doc(alias = "PushTextWrapPos")] - pub fn push_text_wrap_pos_with_pos(&self, wrap_pos_x: f32) -> TextWrapPosStackToken { + pub fn push_text_wrap_pos_with_pos(&self, wrap_pos_x: f32) -> TextWrapPosStackToken<'_> { unsafe { sys::igPushTextWrapPos(wrap_pos_x) }; - TextWrapPosStackToken { _ctx: self.ctx } + TextWrapPosStackToken::new(self) + } + + /// Tab stop enable. + /// Allow focusing using TAB/Shift-TAB, enabled by default but you can + /// disable it for certain widgets + /// + /// Returns a [PushAllowKeyboardFocusToken] that should be dropped. + #[doc(alias = "PushAllowKeyboardFocus")] + pub fn push_allow_keyboard_focus(&self, allow: bool) -> PushAllowKeyboardFocusToken<'_> { + unsafe { sys::igPushAllowKeyboardFocus(allow) }; + PushAllowKeyboardFocusToken::new(self) + } + + /// In 'repeat' mode, button_x functions return repeated true in a typematic + /// manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). + /// Note that you can call IsItemActive() after any Button() to tell if the + /// button is held in the current frame. + /// + /// Returns a [PushButtonRepeatToken] that should be dropped. + #[doc(alias = "PushAllowKeyboardFocus")] + pub fn push_button_repeat(&self, allow: bool) -> PushButtonRepeatToken<'_> { + unsafe { sys::igPushButtonRepeat(allow) }; + PushButtonRepeatToken::new(self) } /// Changes an item flag by pushing a change to the item flag stack. /// /// Returns a `ItemFlagsStackToken` that may be popped by calling `.pop()` - #[doc(alias = "PushItemFlag")] - pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken { + /// + /// ## Deprecated + /// + /// This was deprecated in `0.9.0` because it isn't part of the dear imgui design, + /// and supporting it required a manual implementation of its drop token. + /// + /// Instead, just use [`push_allow_keyboard_focus`] and [`push_button_repeat`]. + /// + /// [`push_allow_keyboard_focus`]: Self::push_allow_keyboard_focus + /// [`push_button_repeat`]: Self::push_button_repeat + #[deprecated( + since = "0.9.0", + note = "use `push_allow_keyboard_focus` or `push_button_repeat` instead" + )] + pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken<'_> { use self::ItemFlag::*; match item_flag { AllowKeyboardFocus(v) => unsafe { sys::igPushAllowKeyboardFocus(v) }, ButtonRepeat(v) => unsafe { sys::igPushButtonRepeat(v) }, } - ItemFlagsStackToken { - discriminant: mem::discriminant(&item_flag), - _ctx: self.ctx, - } + ItemFlagsStackToken::new(self, item_flag) } } @@ -261,54 +291,78 @@ pub enum ItemFlag { ButtonRepeat(bool), } -pub struct ItemWidthStackToken { - _ctx: *const Context, -} +create_token!( + /// Tracks a window that can be ended by calling `.end()` + /// or by dropping. + pub struct ItemWidthStackToken<'ui>; -impl ItemWidthStackToken { - /// Pops a change from the item width stack + /// Ends a window #[doc(alias = "PopItemWidth")] - pub fn pop(mut self, _: &Ui<'_>) { - self._ctx = ptr::null(); - unsafe { sys::igPopItemWidth() }; - } -} + drop { sys::igPopItemWidth() } +); -/// Tracks a change pushed to the text wrap position stack -pub struct TextWrapPosStackToken { - _ctx: *const Context, -} +create_token!( + /// Tracks a window that can be ended by calling `.end()` + /// or by dropping. + pub struct TextWrapPosStackToken<'ui>; -impl TextWrapPosStackToken { - /// Pops a change from the text wrap position stack + /// Ends a window #[doc(alias = "PopTextWrapPos")] - pub fn pop(mut self, _: &Ui<'_>) { - self._ctx = ptr::null(); - unsafe { sys::igPopTextWrapPos() }; + drop { sys::igPopTextWrapPos() } +); + +create_token!( + /// Tracks a window that can be ended by calling `.end()` + /// or by dropping. + pub struct PushAllowKeyboardFocusToken<'ui>; + + /// Ends a window + #[doc(alias = "PopAllowKeyboardFocus")] + drop { sys::igPopAllowKeyboardFocus() } +); + +create_token!( + /// Tracks a window that can be ended by calling `.end()` + /// or by dropping. + pub struct PushButtonRepeatToken<'ui>; + + /// Ends a window + #[doc(alias = "PopButtonRepeat")] + drop { sys::igPopButtonRepeat() } +); + +/// Tracks a change pushed to the item flags stack. +/// +/// The "item flags" stack was a concept invented in imgui-rs that doesn't have an +/// ImGui equivalent. We're phasing these out to make imgui-rs feel simpler to use. +#[must_use] +pub struct ItemFlagsStackToken<'a>( + std::marker::PhantomData>, + mem::Discriminant, +); + +impl<'a> ItemFlagsStackToken<'a> { + /// Creates a new token type. + pub(crate) fn new(_: &crate::Ui<'a>, kind: ItemFlag) -> Self { + Self(std::marker::PhantomData, mem::discriminant(&kind)) + } + + #[inline] + pub fn end(self) { + // left empty for drop } } -/// Tracks a change pushed to the item flags stack -pub struct ItemFlagsStackToken { - discriminant: mem::Discriminant, - _ctx: *const Context, -} - -impl ItemFlagsStackToken { - /// Pops a change from the item flags stack - - #[doc(alias = "PopAllowKeyboardFocus", alias = "PopButtonRepeat")] - pub fn pop(mut self, _: &Ui<'_>) { - self._ctx = ptr::null(); - const ALLOW_KEYBOARD_FOCUS: ItemFlag = ItemFlag::AllowKeyboardFocus(true); - const BUTTON_REPEAT: ItemFlag = ItemFlag::ButtonRepeat(true); - - if self.discriminant == mem::discriminant(&ALLOW_KEYBOARD_FOCUS) { - unsafe { sys::igPopAllowKeyboardFocus() }; - } else if self.discriminant == mem::discriminant(&BUTTON_REPEAT) { - unsafe { sys::igPopButtonRepeat() }; - } else { - unreachable!(); +impl Drop for ItemFlagsStackToken<'_> { + fn drop(&mut self) { + unsafe { + if self.1 == mem::discriminant(&ItemFlag::AllowKeyboardFocus(true)) { + sys::igPopAllowKeyboardFocus(); + } else if self.1 == mem::discriminant(&ItemFlag::ButtonRepeat(true)) { + sys::igPopButtonRepeat(); + } else { + unreachable!(); + } } } } diff --git a/imgui/src/string.rs b/imgui/src/string.rs index d124d85..af6557b 100644 --- a/imgui/src/string.rs +++ b/imgui/src/string.rs @@ -7,16 +7,16 @@ use std::{fmt, ptr}; /// this is the unsafe cell upon which we build our abstraction. #[derive(Debug)] -pub(crate) struct UiBuffer { - buffer: Vec, - max_len: usize, +pub struct UiBuffer { + pub buffer: Vec, + pub max_len: usize, } impl UiBuffer { /// Creates a new max buffer with the given length. - pub fn new(max_len: usize) -> Self { + pub const fn new(max_len: usize) -> Self { Self { - buffer: Vec::with_capacity(max_len), + buffer: Vec::new(), max_len, } } diff --git a/imgui/src/utils.rs b/imgui/src/utils.rs index b977c6d..f819c26 100644 --- a/imgui/src/utils.rs +++ b/imgui/src/utils.rs @@ -177,7 +177,7 @@ impl<'ui> Ui<'ui> { /// style object. #[doc(alias = "GetStyle")] pub fn style_color(&self, style_color: StyleColor) -> [f32; 4] { - self.ctx.style()[style_color] + unsafe { self.style() }.colors[style_color as usize] } /// Returns a shared reference to the current [`Style`]. @@ -193,6 +193,7 @@ impl<'ui> Ui<'ui> { /// pop. The [`clone_style`](Ui::clone_style) version may instead be used to avoid `unsafe`. #[doc(alias = "GetStyle")] pub unsafe fn style(&self) -> &Style { - self.ctx.style() + // safe because Style is a transparent wrapper around sys::ImGuiStyle + &*(sys::igGetStyle() as *const Style) } } diff --git a/imgui/src/widget/drag.rs b/imgui/src/widget/drag.rs index a861365..4b962ba 100644 --- a/imgui/src/widget/drag.rs +++ b/imgui/src/widget/drag.rs @@ -215,7 +215,7 @@ where // we do this ourselves the long way... unsafe { - let buffer = &mut *ui.buffer.get(); + let buffer = &mut *ui.scratch_buffer().get(); buffer.refresh_buffer(); label = buffer.push(self.label); @@ -258,7 +258,7 @@ where let mut max_display_format = std::ptr::null(); // we do this ourselves the long way... - let buffer = &mut *ui.buffer.get(); + let buffer = &mut *ui.scratch_buffer().get(); buffer.refresh_buffer(); label = buffer.push(self.label); From 1d15196b5e6dbc933166c5fbb23c093844c0bcbc Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:08:29 -0400 Subject: [PATCH 02/12] removed the lifetime from the majority of the library --- imgui/src/clipboard.rs | 2 +- imgui/src/columns.rs | 2 +- imgui/src/context.rs | 13 ++++-- imgui/src/drag_drop.rs | 12 ++--- imgui/src/draw_list.rs | 8 ++-- imgui/src/fonts/mod.rs | 2 +- imgui/src/input/keyboard.rs | 2 +- imgui/src/input/mouse.rs | 2 +- imgui/src/input_widget.rs | 24 +++++----- imgui/src/layout.rs | 2 +- imgui/src/lib.rs | 73 ++++++++++++++---------------- imgui/src/list_clipper.rs | 6 +-- imgui/src/plothistogram.rs | 4 +- imgui/src/plotlines.rs | 4 +- imgui/src/popups.rs | 6 +-- imgui/src/stacks.rs | 12 ++--- imgui/src/tables.rs | 16 +++---- imgui/src/tokens.rs | 4 +- imgui/src/utils.rs | 4 +- imgui/src/widget/color_editors.rs | 12 ++--- imgui/src/widget/combo_box.rs | 16 +++---- imgui/src/widget/drag.rs | 8 ++-- imgui/src/widget/image.rs | 4 +- imgui/src/widget/list_box.rs | 6 +-- imgui/src/widget/menu.rs | 8 ++-- imgui/src/widget/misc.rs | 2 +- imgui/src/widget/progress_bar.rs | 2 +- imgui/src/widget/selectable.rs | 4 +- imgui/src/widget/slider.rs | 8 ++-- imgui/src/widget/tab.rs | 10 ++-- imgui/src/widget/text.rs | 2 +- imgui/src/widget/tree.rs | 18 ++++---- imgui/src/window/child_window.rs | 4 +- imgui/src/window/content_region.rs | 2 +- imgui/src/window/mod.rs | 6 +-- imgui/src/window/scroll.rs | 2 +- 36 files changed, 155 insertions(+), 157 deletions(-) diff --git a/imgui/src/clipboard.rs b/imgui/src/clipboard.rs index 38ebc97..f1abb0d 100644 --- a/imgui/src/clipboard.rs +++ b/imgui/src/clipboard.rs @@ -93,7 +93,7 @@ pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: /// # Clipboard #[allow(clippy::fn_address_comparisons)] // This is allowed because although function addresses wont be unique, we just care if its OURS -impl<'ui> Ui<'ui> { +impl Ui { /// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot /// be accessed pub fn clipboard_text(&self) -> Option { diff --git a/imgui/src/columns.rs b/imgui/src/columns.rs index b282e91..ea00f3a 100644 --- a/imgui/src/columns.rs +++ b/imgui/src/columns.rs @@ -2,7 +2,7 @@ use crate::sys; use crate::Ui; /// # Columns -impl<'ui> Ui<'ui> { +impl Ui { #[doc(alias = "Columns")] pub fn columns(&self, count: i32, id: impl AsRef, border: bool) { unsafe { sys::igColumns(count, self.scratch_txt(id), border) } diff --git a/imgui/src/context.rs b/imgui/src/context.rs index a42aed6..e8f3e09 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -60,6 +60,8 @@ pub struct Context { // we also put it in an unsafecell since we're going to give // imgui a mutable pointer to it. clipboard_ctx: Box>, + + ui: Ui, } // This mutex needs to be used to guard all public functions that can affect the underlying @@ -241,6 +243,7 @@ impl Context { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), + ui: Ui(()), } } fn is_current_context(&self) -> bool { @@ -322,6 +325,7 @@ impl SuspendedContext { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), + ui: Ui(()), }; if ctx.is_current_context() { // Oops, the context was activated -> deactivate @@ -515,7 +519,7 @@ impl Context { /// Starts a new frame. #[deprecated(since = "0.9.0", note = "use `new_frame` instead")] - pub fn frame(&mut self) -> Ui<'_> { + pub fn frame(&mut self) -> &mut Ui { self.new_frame() } @@ -526,7 +530,7 @@ impl Context { /// Panics if the context uses a shared font atlas that is already borrowed. /// Do not attempt to borrow the context afterwards, if you are using a shared font atlas. #[doc(alias = "NewFame")] - pub fn new_frame(&mut self) -> Ui<'_> { + pub fn new_frame(&mut self) -> &mut Ui { // Clear default font if it no longer exists. This could be an error in the future let default_font = self.io().font_default; if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() { @@ -540,8 +544,7 @@ impl Context { unsafe { sys::igNewFrame(); } - Ui { - phantom_data: std::marker::PhantomData, - } + + &mut self.ui } } diff --git a/imgui/src/drag_drop.rs b/imgui/src/drag_drop.rs index 2fbf0b5..a6f97f1 100644 --- a/imgui/src/drag_drop.rs +++ b/imgui/src/drag_drop.rs @@ -175,7 +175,7 @@ impl> DragDropSource { /// If you want to pass a simple integer or other "plain old data", take a look at /// [begin_payload](Self::begin_payload). #[inline] - pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option> { + pub fn begin<'ui>(self, ui: &Ui) -> Option> { self.begin_payload(ui, ()) } @@ -224,7 +224,7 @@ impl> DragDropSource { #[inline] pub fn begin_payload<'ui, P: Copy + 'static>( self, - ui: &Ui<'ui>, + ui: &Ui, payload: P, ) -> Option> { unsafe { @@ -266,7 +266,7 @@ impl> DragDropSource { #[inline] pub unsafe fn begin_payload_unchecked<'ui>( &self, - ui: &Ui<'ui>, + ui: &Ui, ptr: *const ffi::c_void, size: usize, ) -> Option> { @@ -283,7 +283,7 @@ impl> DragDropSource { } /// A helper struct for RAII drap-drop support. -pub struct DragDropSourceToolTip<'ui>(PhantomData>); +pub struct DragDropSourceToolTip<'ui>(PhantomData<&'ui Ui>); impl DragDropSourceToolTip<'_> { /// Creates a new tooltip internally. @@ -339,14 +339,14 @@ impl Drop for DragDropSourceToolTip<'_> { /// on this struct. Each of these methods will spit out a _Payload struct with an increasing /// amount of information on the Payload. The absolute safest solution is [accept_payload_empty](Self::accept_payload_empty). #[derive(Debug)] -pub struct DragDropTarget<'ui>(&'ui Ui<'ui>); +pub struct DragDropTarget<'ui>(&'ui Ui); impl<'ui> DragDropTarget<'ui> { /// Creates a new DragDropTarget, holding the [Ui]'s lifetime for the duration /// of its existence. This is required since this struct runs some code on its Drop /// to end the DragDropTarget code. #[doc(alias = "BeginDragDropTarget")] - pub fn new(ui: &'ui Ui<'ui>) -> Option { + pub fn new(ui: &'ui Ui) -> Option { let should_begin = unsafe { sys::igBeginDragDropTarget() }; if should_begin { Some(Self(ui)) diff --git a/imgui/src/draw_list.rs b/imgui/src/draw_list.rs index 27323b0..d58ef6d 100644 --- a/imgui/src/draw_list.rs +++ b/imgui/src/draw_list.rs @@ -75,7 +75,7 @@ enum DrawListType { pub struct DrawListMut<'ui> { draw_list_type: DrawListType, draw_list: *mut ImDrawList, - _phantom: PhantomData<&'ui Ui<'ui>>, + _phantom: PhantomData<&'ui Ui>, } // Lock for each variant of draw list. See https://github.com/imgui-rs/imgui-rs/issues/488 @@ -124,7 +124,7 @@ impl<'ui> DrawListMut<'ui> { } #[doc(alias = "GetWindowDrawList")] - pub(crate) fn window(_: &Ui<'ui>) -> Self { + pub(crate) fn window(_: &Ui) -> Self { Self::lock_draw_list(DrawListType::Window); Self { @@ -135,7 +135,7 @@ impl<'ui> DrawListMut<'ui> { } #[doc(alias = "GetBackgroundDrawList")] - pub(crate) fn background(_: &Ui<'ui>) -> Self { + pub(crate) fn background(_: &Ui) -> Self { Self::lock_draw_list(DrawListType::Background); Self { draw_list: unsafe { sys::igGetBackgroundDrawList() }, @@ -145,7 +145,7 @@ impl<'ui> DrawListMut<'ui> { } #[doc(alias = "GetForegroundDrawList")] - pub(crate) fn foreground(_: &Ui<'ui>) -> Self { + pub(crate) fn foreground(_: &Ui) -> Self { Self::lock_draw_list(DrawListType::Foreground); Self { draw_list: unsafe { sys::igGetForegroundDrawList() }, diff --git a/imgui/src/fonts/mod.rs b/imgui/src/fonts/mod.rs index 3f69efe..f1034a5 100644 --- a/imgui/src/fonts/mod.rs +++ b/imgui/src/fonts/mod.rs @@ -8,7 +8,7 @@ pub mod glyph; pub mod glyph_ranges; /// # Fonts -impl<'ui> Ui<'ui> { +impl Ui { /// Returns the current font #[doc(alias = "GetFont")] pub fn current_font(&self) -> &Font { diff --git a/imgui/src/input/keyboard.rs b/imgui/src/input/keyboard.rs index bab12f4..b425d9c 100644 --- a/imgui/src/input/keyboard.rs +++ b/imgui/src/input/keyboard.rs @@ -91,7 +91,7 @@ impl FocusedWidget { } /// # Input: Keyboard -impl<'ui> Ui<'ui> { +impl Ui { /// Returns the key index of the given key identifier. /// /// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]` diff --git a/imgui/src/input/mouse.rs b/imgui/src/input/mouse.rs index 218b56c..269d4f2 100644 --- a/imgui/src/input/mouse.rs +++ b/imgui/src/input/mouse.rs @@ -89,7 +89,7 @@ fn test_mouse_cursor_variants() { } /// # Input: Mouse -impl<'ui> Ui<'ui> { +impl Ui { /// Returns true if the given mouse button is held down. /// /// Equivalent to indexing the Io struct with the button, e.g. `ui.io()[button]`. diff --git a/imgui/src/input_widget.rs b/imgui/src/input_widget.rs index 200df0f..6e3f073 100644 --- a/imgui/src/input_widget.rs +++ b/imgui/src/input_widget.rs @@ -166,7 +166,7 @@ pub struct InputText<'ui, 'p, L, H = &'static str, T = PassthroughCallback> { buf: &'p mut String, callback_handler: T, flags: InputTextFlags, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L: AsRef> InputText<'ui, 'p, L> { @@ -184,7 +184,7 @@ impl<'ui, 'p, L: AsRef> InputText<'ui, 'p, L> { /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. - pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String) -> Self { + pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String) -> Self { InputText { label, hint: None, @@ -343,7 +343,7 @@ pub struct InputTextMultiline<'ui, 'p, L, T = PassthroughCallback> { flags: InputTextFlags, size: [f32; 2], callback_handler: T, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L: AsRef> InputTextMultiline<'ui, 'p, L, PassthroughCallback> { @@ -361,7 +361,7 @@ impl<'ui, 'p, L: AsRef> InputTextMultiline<'ui, 'p, L, PassthroughCallback> /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. - pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: impl Into) -> Self { + pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String, size: impl Into) -> Self { InputTextMultiline { label, buf, @@ -482,11 +482,11 @@ pub struct InputInt<'ui, 'p, L> { step: i32, step_fast: i32, flags: InputTextFlags, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L: AsRef> InputInt<'ui, 'p, L> { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut i32) -> Self { + pub fn new(ui: &'ui Ui, label: L, value: &'p mut i32) -> Self { InputInt { label, value, @@ -520,11 +520,11 @@ pub struct InputFloat<'ui, 'p, L> { step: f32, step_fast: f32, flags: InputTextFlags, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L: AsRef> InputFloat<'ui, 'p, L> { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut f32) -> Self { + pub fn new(ui: &'ui Ui, label: L, value: &'p mut f32) -> Self { InputFloat { label, value, @@ -559,7 +559,7 @@ macro_rules! impl_input_floatn { label: L, value: &'p mut T, flags: InputTextFlags, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L, T> $InputFloatN<'ui, 'p, L, T> @@ -568,7 +568,7 @@ macro_rules! impl_input_floatn { T: Copy + Into<$MINT_TARGET>, $MINT_TARGET: Into + Into<[f32; $N]>, { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self { + pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self { $InputFloatN { label, value, @@ -614,7 +614,7 @@ macro_rules! impl_input_intn { label: L, value: &'p mut T, flags: InputTextFlags, - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, L, T> $InputIntN<'ui, 'p, L, T> @@ -623,7 +623,7 @@ macro_rules! impl_input_intn { T: Copy + Into<$MINT_TARGET>, $MINT_TARGET: Into + Into<[i32; $N]>, { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self { + pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self { $InputIntN { label, value, diff --git a/imgui/src/layout.rs b/imgui/src/layout.rs index b0cdd16..b385d91 100644 --- a/imgui/src/layout.rs +++ b/imgui/src/layout.rs @@ -12,7 +12,7 @@ create_token!( ); /// # Cursor / Layout -impl<'ui> Ui<'ui> { +impl Ui { /// Renders a separator (generally horizontal). /// /// This becomes a vertical separator inside a menu bar or in horizontal layout mode. diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 05fe3f2..34a7154 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -118,9 +118,7 @@ impl Context { /// A temporary reference for building the user interface for one frame #[derive(Debug)] -pub struct Ui<'ui> { - phantom_data: std::marker::PhantomData<&'ui Context>, -} +pub struct Ui(pub(crate) ()); /// This is our internal buffer that we use for the Ui object. /// @@ -128,7 +126,7 @@ pub struct Ui<'ui> { static mut BUFFER: cell::UnsafeCell = cell::UnsafeCell::new(string::UiBuffer::new(100)); -impl<'ui> Ui<'ui> { +impl Ui { /// This provides access to the backing scratch buffer that we use to write /// strings, along with null-terminators, before we pass normal Rust strs to /// Dear ImGui. @@ -198,29 +196,30 @@ impl<'ui> Ui<'ui> { pub fn clone_style(&self) -> Style { unsafe { *self.style() } } - /// Renders the frame and returns a reference to the resulting draw data - #[doc(alias = "Render", alias = "GetDrawData")] - pub fn render(self) -> &'ui DrawData { - unsafe { - sys::igRender(); - &*(sys::igGetDrawData() as *mut DrawData) - } - } + // /// Renders the frame and returns a reference to the resulting draw data + // #[doc(alias = "Render", alias = "GetDrawData")] + // pub fn render(self) -> &DrawData { + // unsafe { + // sys::igRender(); + // &*(sys::igGetDrawData() as *mut DrawData) + // } + // } } -impl<'a> Drop for Ui<'a> { - #[doc(alias = "EndFrame")] - fn drop(&mut self) { - if !std::thread::panicking() { - unsafe { - sys::igEndFrame(); - } - } - } -} +// TODO JACK YOU NEED TO MOVE THIS! +// impl Drop for Ui { +// #[doc(alias = "EndFrame")] +// fn drop(&mut self) { +// if !std::thread::panicking() { +// unsafe { +// sys::igEndFrame(); +// } +// } +// } +// } /// # Demo, debug, information -impl<'ui> Ui<'ui> { +impl Ui { /// Renders a demo window (previously called a test window), which demonstrates most /// Dear Imgui features. #[doc(alias = "ShowDemoWindow")] @@ -331,7 +330,7 @@ impl<'a> Default for Id<'a> { } } -impl<'ui> Ui<'ui> { +impl Ui { /// # Windows /// Start constructing a window. /// @@ -353,7 +352,7 @@ impl<'ui> Ui<'ui> { /// ui.text("An example"); /// }); /// ``` - pub fn window>(&'ui self, name: Label) -> Window<'ui, '_, Label> { + pub fn window>(&self, name: Label) -> Window<'_, '_, Label> { Window::new(self, name) } @@ -372,13 +371,13 @@ impl<'ui> Ui<'ui> { /// wt.unwrap().end() /// } /// ``` - pub fn child_window>(&'ui self, name: Label) -> ChildWindow<'ui, Label> { + pub fn child_window>(&self, name: Label) -> ChildWindow<'_, Label> { ChildWindow::new(self, name) } } // Widgets: Input -impl<'ui> Ui<'ui> { +impl<'ui> Ui { #[doc(alias = "InputText", alias = "InputTextWithHint")] pub fn input_text<'p, L: AsRef>( &'ui self, @@ -490,7 +489,7 @@ create_token!( ); /// # Tooltips -impl<'ui> Ui<'ui> { +impl Ui { /// Construct a tooltip window that can have any kind of content. /// /// Typically used with `Ui::is_item_hovered()` or some other conditional check. @@ -557,7 +556,7 @@ create_token!( /// imgui can disable widgets so they don't react to mouse/keyboard /// inputs, and are displayed differently (currently dimmed by an /// amount set in [`Style::disabled_alpha`]) -impl<'ui> Ui<'ui> { +impl Ui { /// Creates a scope where interactions are disabled. /// /// Scope ends when returned token is dropped, or `.end()` is @@ -619,7 +618,7 @@ impl<'ui> Ui<'ui> { } // Widgets: ListBox -impl<'ui> Ui<'ui> { +impl Ui { #[doc(alias = "ListBox")] pub fn list_box<'p, StringType: AsRef + ?Sized>( &self, @@ -686,7 +685,7 @@ impl<'ui> Ui<'ui> { // } } -impl<'ui> Ui<'ui> { +impl<'ui> Ui { #[doc(alias = "PlotLines")] pub fn plot_lines<'p, Label: AsRef>( &'ui self, @@ -695,9 +694,7 @@ impl<'ui> Ui<'ui> { ) -> PlotLines<'ui, 'p, Label> { PlotLines::new(self, label, values) } -} -impl<'ui> Ui<'ui> { #[doc(alias = "PlotHistogram")] pub fn plot_histogram<'p, Label: AsRef>( &'ui self, @@ -706,9 +703,7 @@ impl<'ui> Ui<'ui> { ) -> PlotHistogram<'ui, 'p, Label> { PlotHistogram::new(self, label, values) } -} -impl<'ui> Ui<'ui> { /// Calculate the size required for a given text string. /// /// This is the same as [calc_text_size_with_opts](Self::calc_text_size_with_opts) @@ -751,7 +746,7 @@ impl<'ui> Ui<'ui> { } /// # Draw list for custom drawing -impl<'ui> Ui<'ui> { +impl Ui { /// Get access to drawing API /// /// # Examples @@ -783,19 +778,19 @@ impl<'ui> Ui<'ui> { /// ``` #[must_use] #[doc(alias = "GetWindowDrawList")] - pub fn get_window_draw_list(&'ui self) -> DrawListMut<'ui> { + pub fn get_window_draw_list(&self) -> DrawListMut<'_> { DrawListMut::window(self) } #[must_use] #[doc(alias = "GetBackgroundDrawList")] - pub fn get_background_draw_list(&'ui self) -> DrawListMut<'ui> { + pub fn get_background_draw_list(&self) -> DrawListMut<'_> { DrawListMut::background(self) } #[must_use] #[doc(alias = "GetForegroundDrawList")] - pub fn get_foreground_draw_list(&'ui self) -> DrawListMut<'ui> { + pub fn get_foreground_draw_list(&self) -> DrawListMut<'_> { DrawListMut::foreground(self) } } diff --git a/imgui/src/list_clipper.rs b/imgui/src/list_clipper.rs index d4ba021..64a852e 100644 --- a/imgui/src/list_clipper.rs +++ b/imgui/src/list_clipper.rs @@ -22,7 +22,7 @@ impl ListClipper { self } - pub fn begin<'ui>(self, ui: &Ui<'ui>) -> ListClipperToken<'ui> { + pub fn begin(self, ui: &Ui) -> ListClipperToken<'_> { let list_clipper = unsafe { let list_clipper = sys::ImGuiListClipper_ImGuiListClipper(); sys::ImGuiListClipper_Begin(list_clipper, self.items_count, self.items_height); @@ -34,11 +34,11 @@ impl ListClipper { pub struct ListClipperToken<'ui> { list_clipper: *mut sys::ImGuiListClipper, - _phantom: PhantomData<&'ui Ui<'ui>>, + _phantom: PhantomData<&'ui Ui>, } impl<'ui> ListClipperToken<'ui> { - fn new(_: &Ui<'ui>, list_clipper: *mut sys::ImGuiListClipper) -> Self { + fn new(_: &Ui, list_clipper: *mut sys::ImGuiListClipper) -> Self { Self { list_clipper, _phantom: PhantomData, diff --git a/imgui/src/plothistogram.rs b/imgui/src/plothistogram.rs index 0822970..8613ee2 100644 --- a/imgui/src/plothistogram.rs +++ b/imgui/src/plothistogram.rs @@ -12,11 +12,11 @@ pub struct PlotHistogram<'ui, 'p, Label, Overlay = &'static str> { scale_min: f32, scale_max: f32, graph_size: [f32; 2], - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, Label: AsRef> PlotHistogram<'ui, 'p, Label> { - pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self { + pub fn new(ui: &'ui Ui, label: Label, values: &'p [f32]) -> Self { PlotHistogram { label, values, diff --git a/imgui/src/plotlines.rs b/imgui/src/plotlines.rs index a4d8441..ec9441b 100644 --- a/imgui/src/plotlines.rs +++ b/imgui/src/plotlines.rs @@ -12,11 +12,11 @@ pub struct PlotLines<'ui, 'p, Label, Overlay = &'static str> { scale_min: f32, scale_max: f32, graph_size: [f32; 2], - ui: &'ui Ui<'ui>, + ui: &'ui Ui, } impl<'ui, 'p, Label: AsRef> PlotLines<'ui, 'p, Label> { - pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self { + pub fn new(ui: &'ui Ui, label: Label, values: &'p [f32]) -> Self { PlotLines { label, values, diff --git a/imgui/src/popups.rs b/imgui/src/popups.rs index e0b4288..dba4190 100644 --- a/imgui/src/popups.rs +++ b/imgui/src/popups.rs @@ -118,7 +118,7 @@ impl<'p, Label: AsRef> PopupModal<'p, Label> { /// Consume and draw the PopupModal. /// Returns the result of the closure, if it is called. #[doc(alias = "BeginPopupModal")] - pub fn build T>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build T>(self, ui: &Ui, f: F) -> Option { self.begin_popup(ui).map(|_popup| f()) } @@ -128,7 +128,7 @@ impl<'p, Label: AsRef> PopupModal<'p, Label> { /// This should be called *per frame*, whereas [`Ui::open_popup`] /// should be called *once* when you want to actual create the popup. #[doc(alias = "BeginPopupModal")] - pub fn begin_popup<'ui>(self, ui: &Ui<'ui>) -> Option> { + pub fn begin_popup(self, ui: &Ui) -> Option> { let render = unsafe { sys::igBeginPopupModal( ui.scratch_txt(self.label), @@ -148,7 +148,7 @@ impl<'p, Label: AsRef> PopupModal<'p, Label> { } // Widgets: Popups -impl<'ui> Ui<'ui> { +impl Ui { /// Instructs ImGui to open a popup, which must be began with either [`begin_popup`](Self::begin_popup) /// or [`popup`](Self::popup). You also use this function to begin [PopupModal]. /// diff --git a/imgui/src/stacks.rs b/imgui/src/stacks.rs index 44e9632..0cc4b52 100644 --- a/imgui/src/stacks.rs +++ b/imgui/src/stacks.rs @@ -8,7 +8,7 @@ use std::mem; use std::os::raw::{c_char, c_void}; /// # Parameter stacks (shared) -impl<'ui> Ui<'ui> { +impl Ui { /// Switches to the given font by pushing it to the font stack. /// /// Returns a `FontStackToken` that must be popped by calling `.pop()` @@ -177,7 +177,7 @@ unsafe fn push_style_var(style_var: StyleVar) { } /// # Parameter stacks (current window) -impl<'ui> Ui<'ui> { +impl Ui { /// Changes the item width by pushing a change to the item width stack. /// /// Returns an `ItemWidthStackToken` that may be popped by calling `.pop()` @@ -337,13 +337,13 @@ create_token!( /// ImGui equivalent. We're phasing these out to make imgui-rs feel simpler to use. #[must_use] pub struct ItemFlagsStackToken<'a>( - std::marker::PhantomData>, + std::marker::PhantomData<&'a Ui>, mem::Discriminant, ); impl<'a> ItemFlagsStackToken<'a> { /// Creates a new token type. - pub(crate) fn new(_: &crate::Ui<'a>, kind: ItemFlag) -> Self { + pub(crate) fn new(_: &'a crate::Ui, kind: ItemFlag) -> Self { Self(std::marker::PhantomData, mem::discriminant(&kind)) } @@ -384,7 +384,7 @@ impl IdStackToken<'_> { } /// # ID stack -impl<'ui> Ui<'ui> { +impl<'ui> Ui { /// Pushes an identifier to the ID stack. /// This can be called with an integer, a string, or a pointer. /// @@ -462,7 +462,7 @@ impl<'ui> Ui<'ui> { /// }); /// ``` #[doc(alias = "PushId")] - pub fn push_id<'a, I: Into>>(&self, id: I) -> IdStackToken<'ui> { + pub fn push_id<'a, I: Into>>(&'ui self, id: I) -> IdStackToken<'ui> { let id = id.into(); unsafe { diff --git a/imgui/src/tables.rs b/imgui/src/tables.rs index ebd52dd..a5a9503 100644 --- a/imgui/src/tables.rs +++ b/imgui/src/tables.rs @@ -249,7 +249,7 @@ pub enum TableSortDirection { Descending, } -impl<'ui> Ui<'ui> { +impl Ui { /// Begins a table with no flags and with standard sizing contraints. /// /// This does no work on styling the headers (the top row) -- see either @@ -263,7 +263,7 @@ impl<'ui> Ui<'ui> { &self, str_id: impl AsRef, column_count: usize, - ) -> Option> { + ) -> Option> { self.begin_table_with_flags(str_id, column_count, TableFlags::empty()) } @@ -281,7 +281,7 @@ impl<'ui> Ui<'ui> { str_id: impl AsRef, column_count: usize, flags: TableFlags, - ) -> Option> { + ) -> Option> { self.begin_table_with_sizing(str_id, column_count, flags, [0.0, 0.0], 0.0) } @@ -302,7 +302,7 @@ impl<'ui> Ui<'ui> { flags: TableFlags, outer_size: [f32; 2], inner_width: f32, - ) -> Option> { + ) -> Option> { unsafe { sys::igBeginTable( self.scratch_txt(str_id), @@ -324,7 +324,7 @@ impl<'ui> Ui<'ui> { &self, str_id: impl AsRef, column_data: [TableColumnSetup<'a, Name>; N], - ) -> Option> { + ) -> Option> { self.begin_table_header_with_flags(str_id, column_data, TableFlags::empty()) } @@ -338,7 +338,7 @@ impl<'ui> Ui<'ui> { str_id: impl AsRef, column_data: [TableColumnSetup<'a, Name>; N], flags: TableFlags, - ) -> Option> { + ) -> Option> { self.begin_table_header_with_sizing(str_id, column_data, flags, [0.0, 0.0], 0.0) } @@ -354,7 +354,7 @@ impl<'ui> Ui<'ui> { flags: TableFlags, outer_size: [f32; 2], inner_width: f32, - ) -> Option> { + ) -> Option> { self.begin_table_with_sizing(str_id, N, flags, outer_size, inner_width) .map(|data| { for value in column_data { @@ -769,7 +769,7 @@ impl<'a, Name: AsRef> TableColumnSetup<'a, Name> { /// [should_sort]: Self::should_sort /// [specs]: Self::specs /// [set_sorted]: Self::set_sorted -pub struct TableSortSpecsMut<'ui>(*mut sys::ImGuiTableSortSpecs, PhantomData>); +pub struct TableSortSpecsMut<'ui>(*mut sys::ImGuiTableSortSpecs, PhantomData<&'ui Ui>); impl TableSortSpecsMut<'_> { /// Gets the specs for a given sort. In most scenarios, this will be a slice of 1 entry. diff --git a/imgui/src/tokens.rs b/imgui/src/tokens.rs index 7cf20b4..01adf84 100644 --- a/imgui/src/tokens.rs +++ b/imgui/src/tokens.rs @@ -19,11 +19,11 @@ macro_rules! create_token { ) => { #[must_use] $(#[$struct_meta])* - pub struct $token_name<'a>($crate::__core::marker::PhantomData>); + pub struct $token_name<'a>($crate::__core::marker::PhantomData<&'a crate::Ui>); impl<'a> $token_name<'a> { /// Creates a new token type. - pub(crate) fn new(_: &crate::Ui<'a>) -> Self { + pub(crate) fn new(_: &'a crate::Ui) -> Self { Self(std::marker::PhantomData) } diff --git a/imgui/src/utils.rs b/imgui/src/utils.rs index f819c26..144de1b 100644 --- a/imgui/src/utils.rs +++ b/imgui/src/utils.rs @@ -25,7 +25,7 @@ bitflags! { } /// # Item/widget utilities -impl<'ui> Ui<'ui> { +impl Ui { /// Returns `true` if the last item is hovered #[doc(alias = "IsItemHovered")] pub fn is_item_hovered(&self) -> bool { @@ -142,7 +142,7 @@ impl<'ui> Ui<'ui> { } /// # Miscellaneous utilities -impl<'ui> Ui<'ui> { +impl Ui { /// Returns `true` if the rectangle (of given size, starting from cursor position) is visible #[doc(alias = "IsRectVisibleNil")] pub fn is_cursor_rect_visible(&self, size: impl Into) -> bool { diff --git a/imgui/src/widget/color_editors.rs b/imgui/src/widget/color_editors.rs index e7157a5..e02e811 100644 --- a/imgui/src/widget/color_editors.rs +++ b/imgui/src/widget/color_editors.rs @@ -326,7 +326,7 @@ where /// Builds the color editor. /// /// Returns true if the color value was changed. - pub fn build(mut self, ui: &Ui<'_>) -> bool { + pub fn build(mut self, ui: &Ui) -> bool { // if let EditableColor::Float3(_) = self.value { self.flags.insert(ColorEditFlags::NO_ALPHA); @@ -508,7 +508,7 @@ where /// Builds the color editor. /// /// Returns true if the color value was changed. - pub fn build(self, ui: &Ui<'_>) -> bool { + pub fn build(self, ui: &Ui) -> bool { let as_vec4: MintVec4 = (*self.value).into(); let mut as_vec4: [f32; 4] = as_vec4.into(); @@ -694,7 +694,7 @@ where /// Builds the color picker. /// /// Returns true if the color value was changed. - pub fn build(mut self, ui: &Ui<'_>) -> bool { + pub fn build(mut self, ui: &Ui) -> bool { self.flags.insert(ColorEditFlags::NO_ALPHA); let mut value: [f32; 3] = (*self.value).into().into(); let changed = unsafe { @@ -886,7 +886,7 @@ where /// Builds the color picker. /// /// Returns true if the color value was changed. - pub fn build(mut self, ui: &Ui<'_>) -> bool { + pub fn build(mut self, ui: &Ui) -> bool { self.flags.insert(ColorEditFlags::NO_ALPHA); let mut value: [f32; 4] = (*self.value).into().into(); let ref_color = self.ref_color.map(|c| c.as_ptr()).unwrap_or(ptr::null()); @@ -1009,7 +1009,7 @@ impl> ColorButton { /// Builds the color button. /// /// Returns true if this color button was clicked. - pub fn build(self, ui: &Ui<'_>) -> bool { + pub fn build(self, ui: &Ui) -> bool { unsafe { sys::igColorButton( ui.scratch_txt(self.desc_id), @@ -1022,7 +1022,7 @@ impl> ColorButton { } /// # Widgets: Color Editor/Picker -impl<'ui> Ui<'ui> { +impl Ui { /// Initializes current color editor/picker options (generally on application startup) if you /// want to select a default format, picker type, etc. Users will be able to change many /// settings, unless you use .options(false) in your widget builders. diff --git a/imgui/src/widget/combo_box.rs b/imgui/src/widget/combo_box.rs index 342ef69..48cfdfe 100644 --- a/imgui/src/widget/combo_box.rs +++ b/imgui/src/widget/combo_box.rs @@ -142,7 +142,7 @@ impl, Preview: AsRef> ComboBox { /// /// Returns `None` if the combo box is not open and no content should be rendered. #[must_use] - pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option> { + pub fn begin(self, ui: &Ui) -> Option> { let should_render = unsafe { if let Some(preview_value) = self.preview_value { let (ptr_one, ptr_two) = ui.scratch_txt_two(self.label, preview_value); @@ -162,7 +162,7 @@ impl, Preview: AsRef> ComboBox { /// Returns the result of the closure, if it is called. /// /// Note: the closure is not called if the combo box is not open. - pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui, f: F) -> Option { self.begin(ui).map(|_combo| f()) } } @@ -177,7 +177,7 @@ create_token!( ); /// # Convenience functions -impl<'ui> Ui<'ui> { +impl Ui { /// Creates a combo box which can be appended to with `Selectable::new`. /// /// If you do not want to provide a preview, use [`begin_combo_no_preview`]. If you want @@ -193,7 +193,7 @@ impl<'ui> Ui<'ui> { &self, label: impl AsRef, preview_value: impl AsRef, - ) -> Option> { + ) -> Option> { self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::empty()) } @@ -213,7 +213,7 @@ impl<'ui> Ui<'ui> { label: impl AsRef, preview_value: impl AsRef, flags: ComboBoxFlags, - ) -> Option> { + ) -> Option> { self._begin_combo(label, Some(preview_value), flags) } @@ -231,7 +231,7 @@ impl<'ui> Ui<'ui> { /// [begin_combo_no_preview_with_flags]: Ui::begin_combo_no_preview_with_flags #[must_use] #[doc(alias = "BeginCombo")] - pub fn begin_combo_no_preview(&self, label: impl AsRef) -> Option> { + pub fn begin_combo_no_preview(&self, label: impl AsRef) -> Option> { self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::empty()) } @@ -250,7 +250,7 @@ impl<'ui> Ui<'ui> { &self, label: impl AsRef, flags: ComboBoxFlags, - ) -> Option> { + ) -> Option> { self._begin_combo(label, Option::<&'static str>::None, flags) } @@ -260,7 +260,7 @@ impl<'ui> Ui<'ui> { label: impl AsRef, preview_value: Option>, flags: ComboBoxFlags, - ) -> Option> { + ) -> Option> { let should_render = unsafe { let (ptr_one, ptr_two) = self.scratch_txt_with_opt(label, preview_value); sys::igBeginCombo(ptr_one, ptr_two, flags.bits() as i32) diff --git a/imgui/src/widget/drag.rs b/imgui/src/widget/drag.rs index 4b962ba..af25ca1 100644 --- a/imgui/src/widget/drag.rs +++ b/imgui/src/widget/drag.rs @@ -66,7 +66,7 @@ impl, T: DataTypeKind, F: AsRef> Drag { /// Builds a drag slider that is bound to the given value. /// /// Returns true if the slider value was changed. - pub fn build(self, ui: &Ui<'_>, value: &mut T) -> bool { + pub fn build(self, ui: &Ui, value: &mut T) -> bool { unsafe { let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format); @@ -91,7 +91,7 @@ impl, T: DataTypeKind, F: AsRef> Drag { /// Builds a horizontal array of multiple drag sliders attached to the given slice. /// /// Returns true if any slider value was changed. - pub fn build_array(self, ui: &Ui<'_>, values: &mut [T]) -> bool { + pub fn build_array(self, ui: &Ui, values: &mut [T]) -> bool { unsafe { let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format); @@ -208,7 +208,7 @@ where /// /// Returns true if the slider value was changed. #[doc(alias = "DragFloatRange2")] - pub fn build(self, ui: &Ui<'_>, min: &mut f32, max: &mut f32) -> bool { + pub fn build(self, ui: &Ui, min: &mut f32, max: &mut f32) -> bool { let label; let mut display_format = std::ptr::null(); let mut max_display_format = std::ptr::null(); @@ -251,7 +251,7 @@ where /// /// Returns true if the slider value was changed. #[doc(alias = "DragIntRange2")] - pub fn build(self, ui: &Ui<'_>, min: &mut i32, max: &mut i32) -> bool { + pub fn build(self, ui: &Ui, min: &mut i32, max: &mut i32) -> bool { unsafe { let label; let mut display_format = std::ptr::null(); diff --git a/imgui/src/widget/image.rs b/imgui/src/widget/image.rs index 4e2d115..d5aa4b3 100644 --- a/imgui/src/widget/image.rs +++ b/imgui/src/widget/image.rs @@ -58,7 +58,7 @@ impl Image { self } /// Builds the image - pub fn build(self, _: &Ui<'_>) { + pub fn build(self, _: &Ui) { unsafe { sys::igImage( self.texture_id.id() as *mut c_void, @@ -136,7 +136,7 @@ impl ImageButton { self } /// Builds the image button - pub fn build(self, _: &Ui<'_>) -> bool { + pub fn build(self, _: &Ui) -> bool { unsafe { sys::igImageButton( self.texture_id.id() as *mut c_void, diff --git a/imgui/src/widget/list_box.rs b/imgui/src/widget/list_box.rs index 922d871..e01bdc2 100644 --- a/imgui/src/widget/list_box.rs +++ b/imgui/src/widget/list_box.rs @@ -39,7 +39,7 @@ impl> ListBox { /// /// Returns `None` if the list box is not open and no content should be rendered. #[must_use] - pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option> { + pub fn begin(self, ui: &Ui) -> Option> { let should_render = unsafe { sys::igBeginListBox(ui.scratch_txt(self.label), self.size.into()) }; if should_render { @@ -52,7 +52,7 @@ impl> ListBox { /// Returns the result of the closure, if it is called. /// /// Note: the closure is not called if the list box is not open. - pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui, f: F) -> Option { self.begin(ui).map(|_list| f()) } } @@ -71,7 +71,7 @@ impl> ListBox { /// Builds a simple list box for choosing from a slice of values pub fn build_simple( self, - ui: &Ui<'_>, + ui: &Ui, current_item: &mut usize, items: &[V], label_fn: &L, diff --git a/imgui/src/widget/menu.rs b/imgui/src/widget/menu.rs index 0ac02e5..0b4a263 100644 --- a/imgui/src/widget/menu.rs +++ b/imgui/src/widget/menu.rs @@ -3,7 +3,7 @@ use crate::sys; use crate::Ui; /// # Widgets: Menus -impl<'ui> Ui<'ui> { +impl Ui { /// Creates and starts appending to a full-screen menu bar. /// /// Returns `Some(MainMenuBarToken)` if the menu bar is visible. After content has been @@ -12,7 +12,7 @@ impl<'ui> Ui<'ui> { /// Returns `None` if the menu bar is not visible and no content should be rendered. #[must_use] #[doc(alias = "BeginMainMenuBar")] - pub fn begin_main_menu_bar(&self) -> Option> { + pub fn begin_main_menu_bar(&self) -> Option> { if unsafe { sys::igBeginMainMenuBar() } { Some(MainMenuBarToken::new(self)) } else { @@ -167,7 +167,7 @@ impl, Shortcut: AsRef> MenuItem { /// /// Returns true if the menu item is activated. #[doc(alias = "MenuItemBool")] - pub fn build(self, ui: &Ui<'_>) -> bool { + pub fn build(self, ui: &Ui) -> bool { unsafe { let (label, shortcut) = ui.scratch_txt_with_opt(self.label, self.shortcut); sys::igMenuItem_Bool(label, shortcut, self.selected, self.enabled) @@ -176,7 +176,7 @@ impl, Shortcut: AsRef> MenuItem { #[doc(alias = "MenuItemBool")] /// Builds the menu item using a mutable reference to selected state. - pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool { + pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool { if self.selected(*selected).build(ui) { *selected = !*selected; true diff --git a/imgui/src/widget/misc.rs b/imgui/src/widget/misc.rs index f79e128..288c341 100644 --- a/imgui/src/widget/misc.rs +++ b/imgui/src/widget/misc.rs @@ -19,7 +19,7 @@ bitflags!( ); /// # Widgets: Miscellaneous -impl<'ui> Ui<'ui> { +impl Ui { /// Renders a clickable button. /// /// Returns true if this button was clicked. diff --git a/imgui/src/widget/progress_bar.rs b/imgui/src/widget/progress_bar.rs index eb641ef..514127d 100644 --- a/imgui/src/widget/progress_bar.rs +++ b/imgui/src/widget/progress_bar.rs @@ -62,7 +62,7 @@ impl> ProgressBar { } /// Builds the progress bar - pub fn build(self, ui: &Ui<'_>) { + pub fn build(self, ui: &Ui) { unsafe { sys::igProgressBar( self.fraction, diff --git a/imgui/src/widget/selectable.rs b/imgui/src/widget/selectable.rs index 48eceaa..2bfe93b 100644 --- a/imgui/src/widget/selectable.rs +++ b/imgui/src/widget/selectable.rs @@ -108,7 +108,7 @@ impl> Selectable { /// Builds the selectable. /// /// Returns true if the selectable was clicked. - pub fn build(self, ui: &Ui<'_>) -> bool { + pub fn build(self, ui: &Ui) -> bool { unsafe { sys::igSelectable_Bool( ui.scratch_txt(self.label), @@ -120,7 +120,7 @@ impl> Selectable { } /// Builds the selectable using a mutable reference to selected state. - pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool { + pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool { if self.selected(*selected).build(ui) { *selected = !*selected; true diff --git a/imgui/src/widget/slider.rs b/imgui/src/widget/slider.rs index 5b7d1c9..c473730 100644 --- a/imgui/src/widget/slider.rs +++ b/imgui/src/widget/slider.rs @@ -96,7 +96,7 @@ where /// Builds a slider that is bound to the given value. /// /// Returns true if the slider value was changed. - pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool { + pub fn build(self, ui: &Ui, value: &mut Data) -> bool { unsafe { let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); @@ -114,7 +114,7 @@ where /// Builds a horizontal array of multiple sliders attached to the given slice. /// /// Returns true if any slider value was changed. - pub fn build_array(self, ui: &Ui<'_>, values: &mut [Data]) -> bool { + pub fn build_array(self, ui: &Ui, values: &mut [Data]) -> bool { unsafe { let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); @@ -222,7 +222,7 @@ where /// Builds a vertical slider that is bound to the given value. /// /// Returns true if the slider value was changed. - pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool { + pub fn build(self, ui: &Ui, value: &mut Data) -> bool { unsafe { let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); @@ -326,7 +326,7 @@ where /// Builds an angle slider that is bound to the given value (in radians). /// /// Returns true if the slider value was changed. - pub fn build(self, ui: &Ui<'_>, value_rad: &mut f32) -> bool { + pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool { unsafe { let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format); diff --git a/imgui/src/widget/tab.rs b/imgui/src/widget/tab.rs index b1bedce..54b43a0 100644 --- a/imgui/src/widget/tab.rs +++ b/imgui/src/widget/tab.rs @@ -87,7 +87,7 @@ impl> TabBar { } #[must_use] - pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option> { + pub fn begin(self, ui: &Ui) -> Option> { ui.tab_bar_with_flags(self.id, self.flags) } @@ -95,7 +95,7 @@ impl> TabBar { /// Returns the result of the closure, if it is called. /// /// Note: the closure is not called if no tabbar content is visible - pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui, f: F) -> Option { self.begin(ui).map(|_tab| f()) } } @@ -144,7 +144,7 @@ impl<'a, T: AsRef> TabItem<'a, T> { } #[must_use] - pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option> { + pub fn begin(self, ui: &Ui) -> Option> { ui.tab_item_with_flags(self.label, self.opened, self.flags) } @@ -152,7 +152,7 @@ impl<'a, T: AsRef> TabItem<'a, T> { /// Returns the result of the closure, if it is called. /// /// Note: the closure is not called if the tab item is not selected - pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui, f: F) -> Option { self.begin(ui).map(|_tab| f()) } } @@ -166,7 +166,7 @@ create_token!( drop { sys::igEndTabItem() } ); -impl Ui<'_> { +impl Ui { /// Creates a tab bar and returns a tab bar token, allowing you to append /// Tab items afterwards. This passes no flags. To pass flags explicitly, /// use [tab_bar_with_flags](Self::tab_bar_with_flags). diff --git a/imgui/src/widget/text.rs b/imgui/src/widget/text.rs index 99bb0d4..abe38be 100644 --- a/imgui/src/widget/text.rs +++ b/imgui/src/widget/text.rs @@ -13,7 +13,7 @@ fn fmt_ptr() -> *const c_char { } /// # Widgets: Text -impl<'ui> Ui<'ui> { +impl Ui { /// Renders simple text #[doc(alias = "TextUnformatted")] pub fn text>(&self, text: T) { diff --git a/imgui/src/widget/tree.rs b/imgui/src/widget/tree.rs index 06abafc..4f18b16 100644 --- a/imgui/src/widget/tree.rs +++ b/imgui/src/widget/tree.rs @@ -241,7 +241,7 @@ impl, L: AsRef> TreeNode { /// rendered, the token can be popped by calling `.pop()`. /// /// Returns `None` if the tree node is not open and no content should be rendered. - pub fn push<'ui>(self, ui: &Ui<'ui>) -> Option> { + pub fn push(self, ui: &Ui) -> Option> { let open = unsafe { if self.opened_cond != Condition::Never { sys::igSetNextItemOpen(self.opened, self.opened_cond as i32); @@ -282,7 +282,7 @@ impl, L: AsRef> TreeNode { /// Returns the result of the closure, if it is called. /// /// Note: the closure is not called if the tree node is not open. - pub fn build R>(self, ui: &Ui<'_>, f: F) -> Option { + pub fn build R>(self, ui: &Ui, f: F) -> Option { self.push(ui).map(|_node| f()) } } @@ -292,11 +292,11 @@ impl, L: AsRef> TreeNode { /// If `TreeNodeFlags::NO_TREE_PUSH_ON_OPEN` was used when this token was created, calling `.pop()` /// is not mandatory and is a no-op. #[must_use] -pub struct TreeNodeToken<'a>(core::marker::PhantomData>, bool); +pub struct TreeNodeToken<'a>(core::marker::PhantomData<&'a crate::Ui>, bool); impl<'a> TreeNodeToken<'a> { /// Creates a new token type. This takes a bool for the no-op variant on NO_TREE_PUSH_ON_OPEN. - pub(crate) fn new(_: &crate::Ui<'a>, execute_drop: bool) -> Self { + pub(crate) fn new(_: &crate::Ui, execute_drop: bool) -> Self { Self(std::marker::PhantomData, execute_drop) } @@ -408,7 +408,7 @@ impl> CollapsingHeader { /// /// This is the same as [build](Self::build) but is provided for consistent naming. #[must_use] - pub fn begin(self, ui: &Ui<'_>) -> bool { + pub fn begin(self, ui: &Ui) -> bool { self.build(ui) } @@ -419,7 +419,7 @@ impl> CollapsingHeader { /// This is the same as [build_with_close_button](Self::build_with_close_button) /// but is provided for consistent naming. #[must_use] - pub fn begin_with_close_button(self, ui: &Ui<'_>, opened: &mut bool) -> bool { + pub fn begin_with_close_button(self, ui: &Ui, opened: &mut bool) -> bool { self.build_with_close_button(ui, opened) } @@ -428,7 +428,7 @@ impl> CollapsingHeader { /// Returns true if the collapsing header is open and content should be rendered. #[must_use] #[inline] - pub fn build(self, ui: &Ui<'_>) -> bool { + pub fn build(self, ui: &Ui) -> bool { unsafe { sys::igCollapsingHeader_TreeNodeFlags( ui.scratch_txt(self.label), @@ -442,7 +442,7 @@ impl> CollapsingHeader { /// Returns true if the collapsing header is open and content should be rendered. #[must_use] #[inline] - pub fn build_with_close_button(self, ui: &Ui<'_>, opened: &mut bool) -> bool { + pub fn build_with_close_button(self, ui: &Ui, opened: &mut bool) -> bool { unsafe { sys::igCollapsingHeader_BoolPtr( ui.scratch_txt(self.label), @@ -453,7 +453,7 @@ impl> CollapsingHeader { } } -impl Ui<'_> { +impl Ui { /// Constructs a new collapsing header #[doc(alias = "CollapsingHeader")] pub fn collapsing_header(&self, label: impl AsRef, flags: TreeNodeFlags) -> bool { diff --git a/imgui/src/window/child_window.rs b/imgui/src/window/child_window.rs index 8b83df4..5694305 100644 --- a/imgui/src/window/child_window.rs +++ b/imgui/src/window/child_window.rs @@ -9,7 +9,7 @@ use crate::Ui; #[derive(Copy, Clone, Debug)] #[must_use] pub struct ChildWindow<'ui, Label> { - ui: &'ui Ui<'ui>, + ui: &'ui Ui, name: Label, flags: WindowFlags, size: [f32; 2], @@ -22,7 +22,7 @@ pub struct ChildWindow<'ui, Label> { impl<'ui, Label: AsRef> ChildWindow<'ui, Label> { /// Creates a new child window builder with the given ID #[doc(alias = "BeginChildID")] - pub fn new(ui: &'ui Ui<'ui>, name: Label) -> ChildWindow<'ui, Label> { + pub fn new(ui: &'ui Ui, name: Label) -> ChildWindow<'ui, Label> { ChildWindow { ui, name, diff --git a/imgui/src/window/content_region.rs b/imgui/src/window/content_region.rs index 40c2190..27270e2 100644 --- a/imgui/src/window/content_region.rs +++ b/imgui/src/window/content_region.rs @@ -2,7 +2,7 @@ use crate::sys; use crate::Ui; /// # Content region -impl<'ui> Ui<'ui> { +impl Ui { /// Returns the current content boundaries (in *window coordinates*) #[doc(alias = "GetContentRegionMax")] pub fn content_region_max(&self) -> [f32; 2] { diff --git a/imgui/src/window/mod.rs b/imgui/src/window/mod.rs index 6183ca8..00e7f65 100644 --- a/imgui/src/window/mod.rs +++ b/imgui/src/window/mod.rs @@ -111,7 +111,7 @@ bitflags! { } /// # Window utilities -impl<'ui> Ui<'ui> { +impl Ui { /// Returns true if the current window appeared during this frame #[doc(alias = "IsWindowAppearing")] pub fn is_window_appearing(&self) -> bool { @@ -162,7 +162,7 @@ impl<'ui> Ui<'ui> { #[derive(Debug)] #[must_use] pub struct Window<'ui, 'a, Label> { - ui: &'ui Ui<'ui>, + ui: &'ui Ui, name: Label, opened: Option<&'a mut bool>, flags: WindowFlags, @@ -181,7 +181,7 @@ pub struct Window<'ui, 'a, Label> { impl<'ui, 'a, Label: AsRef> Window<'ui, 'a, Label> { /// Typically created via [`Ui::window`] - pub fn new(ui: &'ui Ui<'ui>, name: Label) -> Self { + pub fn new(ui: &'ui Ui, name: Label) -> Self { Window { ui, name, diff --git a/imgui/src/window/scroll.rs b/imgui/src/window/scroll.rs index 386002a..cd9174a 100644 --- a/imgui/src/window/scroll.rs +++ b/imgui/src/window/scroll.rs @@ -2,7 +2,7 @@ use crate::sys; use crate::Ui; /// # Window scrolling -impl<'ui> Ui<'ui> { +impl Ui { /// Returns the horizontal scrolling position. /// /// Value is between 0.0 and self.scroll_max_x(). From 41ab3643840f46a512e5f80e8975b01deafbc1a8 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:11:39 -0400 Subject: [PATCH 03/12] and added the thorn in this method --- imgui/src/context.rs | 16 ++++++++++++++-- imgui/src/lib.rs | 20 -------------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index e8f3e09..b9e97cc 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -10,8 +10,8 @@ use crate::clipboard::{ClipboardBackend, ClipboardContext}; use crate::fonts::atlas::{FontAtlas, FontAtlasRefMut, FontId, SharedFontAtlas}; use crate::io::Io; use crate::style::Style; -use crate::sys; use crate::Ui; +use crate::{sys, DrawData}; /// An imgui-rs context. /// @@ -518,7 +518,6 @@ impl Context { } /// Starts a new frame. - #[deprecated(since = "0.9.0", note = "use `new_frame` instead")] pub fn frame(&mut self) -> &mut Ui { self.new_frame() } @@ -547,4 +546,17 @@ impl Context { &mut self.ui } + + /// Renders the frame and returns a reference to the resulting draw data. + /// + /// This should only be called after calling [`new_frame`]. + /// + /// [`new_frame`]: Self::new_frame + #[doc(alias = "Render", alias = "GetDrawData")] + pub fn render(&mut self) -> &DrawData { + unsafe { + sys::igRender(); + &*(sys::igGetDrawData() as *mut DrawData) + } + } } diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 34a7154..4c2d040 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -196,28 +196,8 @@ impl Ui { pub fn clone_style(&self) -> Style { unsafe { *self.style() } } - // /// Renders the frame and returns a reference to the resulting draw data - // #[doc(alias = "Render", alias = "GetDrawData")] - // pub fn render(self) -> &DrawData { - // unsafe { - // sys::igRender(); - // &*(sys::igGetDrawData() as *mut DrawData) - // } - // } } -// TODO JACK YOU NEED TO MOVE THIS! -// impl Drop for Ui { -// #[doc(alias = "EndFrame")] -// fn drop(&mut self) { -// if !std::thread::panicking() { -// unsafe { -// sys::igEndFrame(); -// } -// } -// } -// } - /// # Demo, debug, information impl Ui { /// Renders a demo window (previously called a test window), which demonstrates most From b30cb740ba8b422d19cbc753f1aa42983008a80b Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:15:02 -0400 Subject: [PATCH 04/12] aaaand fixed up the examples --- imgui-examples/examples/support/mod.rs | 2 +- imgui-examples/examples/test_window_impl.rs | 6 +++--- imgui-glow-renderer/examples/01_basic.rs | 4 ++-- imgui-glow-renderer/examples/02_triangle.rs | 2 +- imgui-glow-renderer/examples/03_triangle_gles.rs | 2 +- imgui-glow-renderer/examples/04_custom_textures.rs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs index 2a5c9d5..0b2dcbc 100644 --- a/imgui-examples/examples/support/mod.rs +++ b/imgui-examples/examples/support/mod.rs @@ -121,7 +121,7 @@ impl System { let mut target = display.draw(); target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); platform.prepare_render(&ui, gl_window.window()); - let draw_data = ui.render(); + let draw_data = imgui.render(); renderer .render(&mut target, draw_data) .expect("Rendering failed"); diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index a43e95b..f62eaa0 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -330,7 +330,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { window = window.opened(opened) } window.build(|| { - ui.push_item_width(-140.0); + let _w = ui.push_item_width(-140.0); ui.text(format!("dear imgui says hello. ({})", imgui::dear_imgui_version())); if let Some(menu_bar) = ui.begin_menu_bar() { if let Some(menu) = ui.begin_menu("Menu") { @@ -827,7 +827,7 @@ CTRL+click on individual component to input value.\n", }); } -fn show_example_app_main_menu_bar<'a>(ui: &Ui<'a>, state: &mut State) { +fn show_example_app_main_menu_bar(ui: &Ui, state: &mut State) { if let Some(menu_bar) = ui.begin_main_menu_bar() { if let Some(menu) = ui.begin_menu("File") { show_example_menu_file(ui, &mut state.file_menu); @@ -849,7 +849,7 @@ fn show_example_app_main_menu_bar<'a>(ui: &Ui<'a>, state: &mut State) { } } -fn show_example_menu_file<'a>(ui: &Ui<'a>, state: &mut FileMenuState) { +fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) { MenuItem::new("(dummy menu)").enabled(false).build(ui); MenuItem::new("New").build(ui); MenuItem::new("Open").shortcut("Ctrl+O").build(ui); diff --git a/imgui-glow-renderer/examples/01_basic.rs b/imgui-glow-renderer/examples/01_basic.rs index 0ca9091..ffdd4c6 100644 --- a/imgui-glow-renderer/examples/01_basic.rs +++ b/imgui-glow-renderer/examples/01_basic.rs @@ -51,8 +51,8 @@ fn main() { let ui = imgui_context.frame(); ui.show_demo_window(&mut true); - winit_platform.prepare_render(&ui, window.window()); - let draw_data = ui.render(); + winit_platform.prepare_render(ui, window.window()); + let draw_data = imgui_context.render(); // This is the only extra render step to add ig_renderer diff --git a/imgui-glow-renderer/examples/02_triangle.rs b/imgui-glow-renderer/examples/02_triangle.rs index 55a2b4a..6bc6c1c 100644 --- a/imgui-glow-renderer/examples/02_triangle.rs +++ b/imgui-glow-renderer/examples/02_triangle.rs @@ -42,7 +42,7 @@ fn main() { ui.show_demo_window(&mut true); winit_platform.prepare_render(&ui, window.window()); - let draw_data = ui.render(); + let draw_data = imgui_context.render(); // Render imgui on top of it ig_renderer diff --git a/imgui-glow-renderer/examples/03_triangle_gles.rs b/imgui-glow-renderer/examples/03_triangle_gles.rs index 989a788..1d92da2 100644 --- a/imgui-glow-renderer/examples/03_triangle_gles.rs +++ b/imgui-glow-renderer/examples/03_triangle_gles.rs @@ -56,7 +56,7 @@ fn main() { ui.show_demo_window(&mut true); winit_platform.prepare_render(&ui, window.window()); - let draw_data = ui.render(); + let draw_data = imgui_context.render(); // Render imgui on top ig_renderer diff --git a/imgui-glow-renderer/examples/04_custom_textures.rs b/imgui-glow-renderer/examples/04_custom_textures.rs index 70e4d95..db56dc8 100644 --- a/imgui-glow-renderer/examples/04_custom_textures.rs +++ b/imgui-glow-renderer/examples/04_custom_textures.rs @@ -59,7 +59,7 @@ fn main() { textures_ui.show(&ui); winit_platform.prepare_render(&ui, window.window()); - let draw_data = ui.render(); + let draw_data = imgui_context.render(); ig_renderer .render(&gl, &textures, draw_data) .expect("error rendering imgui"); From 11b7e87c646294fa4a7a2f575dd3074c1a9a2574 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:18:58 -0400 Subject: [PATCH 05/12] clippy fixes --- imgui-examples/examples/support/mod.rs | 2 +- imgui-glow-renderer/examples/02_triangle.rs | 2 +- imgui-glow-renderer/examples/03_triangle_gles.rs | 2 +- imgui-glow-renderer/examples/04_custom_textures.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs index 0b2dcbc..aea615a 100644 --- a/imgui-examples/examples/support/mod.rs +++ b/imgui-examples/examples/support/mod.rs @@ -120,7 +120,7 @@ impl System { let gl_window = display.gl_window(); let mut target = display.draw(); target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); - platform.prepare_render(&ui, gl_window.window()); + platform.prepare_render(ui, gl_window.window()); let draw_data = imgui.render(); renderer .render(&mut target, draw_data) diff --git a/imgui-glow-renderer/examples/02_triangle.rs b/imgui-glow-renderer/examples/02_triangle.rs index 6bc6c1c..f1c1e98 100644 --- a/imgui-glow-renderer/examples/02_triangle.rs +++ b/imgui-glow-renderer/examples/02_triangle.rs @@ -41,7 +41,7 @@ fn main() { let ui = imgui_context.frame(); ui.show_demo_window(&mut true); - winit_platform.prepare_render(&ui, window.window()); + winit_platform.prepare_render(ui, window.window()); let draw_data = imgui_context.render(); // Render imgui on top of it diff --git a/imgui-glow-renderer/examples/03_triangle_gles.rs b/imgui-glow-renderer/examples/03_triangle_gles.rs index 1d92da2..b20d258 100644 --- a/imgui-glow-renderer/examples/03_triangle_gles.rs +++ b/imgui-glow-renderer/examples/03_triangle_gles.rs @@ -55,7 +55,7 @@ fn main() { let ui = imgui_context.frame(); ui.show_demo_window(&mut true); - winit_platform.prepare_render(&ui, window.window()); + winit_platform.prepare_render(ui, window.window()); let draw_data = imgui_context.render(); // Render imgui on top diff --git a/imgui-glow-renderer/examples/04_custom_textures.rs b/imgui-glow-renderer/examples/04_custom_textures.rs index db56dc8..5020386 100644 --- a/imgui-glow-renderer/examples/04_custom_textures.rs +++ b/imgui-glow-renderer/examples/04_custom_textures.rs @@ -56,9 +56,9 @@ fn main() { unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }; let ui = imgui_context.frame(); - textures_ui.show(&ui); + textures_ui.show(ui); - winit_platform.prepare_render(&ui, window.window()); + winit_platform.prepare_render(ui, window.window()); let draw_data = imgui_context.render(); ig_renderer .render(&gl, &textures, draw_data) From 9b6f6c0fb84ac3abd67dbc16712a3137401b55d3 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 21:49:23 -0400 Subject: [PATCH 06/12] fix tests --- imgui/src/context.rs | 4 ++++ imgui/src/drag_drop.rs | 8 ++++---- imgui/src/input/mouse.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index b9e97cc..f4f6392 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -259,6 +259,10 @@ impl Drop for Context { // If this context is the active context, Dear ImGui automatically deactivates it during // destruction unsafe { + // end the frame if necessary... + if !sys::igGetCurrentContext().is_null() && sys::igGetFrameCount() > 0 { + sys::igEndFrame(); + } sys::igDestroyContext(self.raw); } } diff --git a/imgui/src/drag_drop.rs b/imgui/src/drag_drop.rs index a6f97f1..1f209a5 100644 --- a/imgui/src/drag_drop.rs +++ b/imgui/src/drag_drop.rs @@ -74,7 +74,7 @@ bitflags!( /// /// ```no_run /// # use imgui::*; -/// fn show_ui(ui: &Ui<'_>) { +/// fn show_ui(ui: &Ui) { /// ui.button("Hello, I am a drag source!"); /// /// // Creates an empty DragSource with no tooltip @@ -141,7 +141,7 @@ impl> DragDropSource { /// /// ```no_run /// # use imgui::*; - /// fn show_ui(ui: &Ui<'_>, drop_message: &mut Option) { + /// fn show_ui(ui: &Ui, drop_message: &mut Option) { /// ui.button("Drag me!"); /// /// let drag_drop_name = "Test Drag"; @@ -194,7 +194,7 @@ impl> DragDropSource { /// /// ```no_run /// # use imgui::*; - /// fn show_ui(ui: &Ui<'_>) { + /// fn show_ui(ui: &Ui) { /// ui.button("Drag me!"); /// /// let drag_drop_name = "Test Drag"; @@ -310,7 +310,7 @@ impl Drop for DragDropSourceToolTip<'_> { /// /// ```no_run /// # use imgui::*; -/// fn show_ui(ui: &Ui<'_>) { +/// fn show_ui(ui: &Ui) { /// // Drop something on this button please! /// ui.button("Hello, I am a drag Target!"); /// diff --git a/imgui/src/input/mouse.rs b/imgui/src/input/mouse.rs index 269d4f2..7664455 100644 --- a/imgui/src/input/mouse.rs +++ b/imgui/src/input/mouse.rs @@ -242,6 +242,7 @@ fn test_mouse_down_clicked_released() { assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_released(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; @@ -250,6 +251,7 @@ fn test_mouse_down_clicked_released() { assert!(ui.is_any_mouse_down()); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_released(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); @@ -257,6 +259,7 @@ fn test_mouse_down_clicked_released() { assert!(ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_released(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = false; @@ -265,6 +268,7 @@ fn test_mouse_down_clicked_released() { assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); assert!(ui.is_mouse_released(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); @@ -272,6 +276,7 @@ fn test_mouse_down_clicked_released() { assert!(!ui.is_any_mouse_down()); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_released(button)); + let _ = ctx.render(); } } } @@ -279,6 +284,7 @@ fn test_mouse_down_clicked_released() { #[test] fn test_mouse_double_click() { let (_guard, mut ctx) = crate::test::test_ctx_initialized(); + // Workaround for dear imgui bug/feature: // If a button is clicked before io.mouse_double_click_time seconds has passed after the // context is initialized, the single click is interpreted as a double-click. This happens @@ -288,6 +294,7 @@ fn test_mouse_double_click() { // Pass one second of time ctx.io_mut().delta_time = 1.0; let _ = ctx.new_frame(); + let _ = ctx.render(); } // Fast clicks ctx.io_mut().delta_time = 1.0 / 60.0; @@ -297,34 +304,40 @@ fn test_mouse_double_click() { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = false; let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } } // Slow clicks @@ -335,34 +348,40 @@ fn test_mouse_double_click() { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = false; let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; let ui = ctx.new_frame(); assert!(ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } { let ui = ctx.new_frame(); assert!(!ui.is_mouse_clicked(button)); assert!(!ui.is_mouse_double_clicked(button)); + let _ = ctx.render(); } } } @@ -392,6 +411,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 0.0] ); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; @@ -403,6 +423,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 0.0] ); + let _ = ctx.render(); } { ctx.io_mut().mouse_pos = [0.0, 100.0]; @@ -414,6 +435,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 0.0] ); + let _ = ctx.render(); } { ctx.io_mut().mouse_pos = [0.0, 200.0]; @@ -425,6 +447,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 200.0] ); + let _ = ctx.render(); } { ctx.io_mut().mouse_pos = [10.0, 10.0]; @@ -437,6 +460,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [10.0, 10.0] ); + let _ = ctx.render(); } { ctx.io_mut()[button] = true; @@ -448,6 +472,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 0.0] ); + let _ = ctx.render(); } { ctx.io_mut().mouse_pos = [180.0, 180.0]; @@ -467,6 +492,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [0.0, 0.0] ); + let _ = ctx.render(); } { ctx.io_mut().mouse_pos = [200.0, 200.0]; @@ -478,6 +504,7 @@ fn test_mouse_drags() { ui.mouse_drag_delta_with_threshold(button, 200.0), [20.0, 20.0] ); + let _ = ctx.render(); } } } From 63267ddf563f660db5dfe33836d98a2ec3237bcd Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Sun, 26 Sep 2021 22:27:19 -0400 Subject: [PATCH 07/12] better support for non-send-sync --- imgui/src/context.rs | 4 ++-- imgui/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index f4f6392..29b7bc5 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -243,7 +243,7 @@ impl Context { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), - ui: Ui(()), + ui: Ui(().into()), } } fn is_current_context(&self) -> bool { @@ -329,7 +329,7 @@ impl SuspendedContext { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), - ui: Ui(()), + ui: Ui(().into()), }; if ctx.is_current_context() { // Oops, the context was activated -> deactivate diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 4c2d040..f6338cf 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -118,7 +118,7 @@ impl Context { /// A temporary reference for building the user interface for one frame #[derive(Debug)] -pub struct Ui(pub(crate) ()); +pub struct Ui(pub(crate) cell::UnsafeCell<()>); /// This is our internal buffer that we use for the Ui object. /// From 2a8374a339ca5919865d7d4f6825fc4c28da281c Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Mon, 27 Sep 2021 14:42:15 -0400 Subject: [PATCH 08/12] removed ZST for `Ui` and changed shared font atlas to be based on UnsafeCell --- CHANGELOG.markdown | 4 +++ imgui/src/context.rs | 66 ++++++++++++++-------------------------- imgui/src/fonts/atlas.rs | 2 +- imgui/src/lib.rs | 23 ++++++-------- 4 files changed, 38 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index c89367b..9ac6d8e 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -6,6 +6,10 @@ - BREAKING: Removed `push_style_colors` and `push_style_vars`. Instead, use `push_style_color` in a loop. This was deprecated in `0.7.0` and should have been removed in `0.8.0`. This also removes their associated tokens. +- BREAKING: Ui now does not have a lifetime associated with it, but is only ever given to users in the form of `&mut Ui`. Additionally, the `render` function has been moved to the `Context` instead of `Ui`. + +- BREAKING: `SharedFontAtlas` now uses `UnsafeCell` rather than `Rc` as its wrapper -- this simplifies the codebase and more accurately reflects how we expect `SharedFontAtlas` to be used (ie, you're probably going to set it up once, and then give it around, rather than constantly edit it). `SharedFontAtlas` users, if this change is very bad for you, please let us know with issues! + ## [0.8.0] - 2021-09-17 Welcome to the `0.8.0` update. This is one of the largest updates imgui-rs has ever seen; it will generate errors in a `0.7` project, but hopefully it should be both quick to fix, and enjoyable to update. See our [release page](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.8.0) for more information and a list of contributors to this cycle. Thank you to everyone who uses `imgui-rs`, files issues, and spend their time and effort to PR new changes into the codebase. Because of all that effort, this is by far the best `imgui-rs` has looked! diff --git a/imgui/src/context.rs b/imgui/src/context.rs index 29b7bc5..3acda71 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -1,13 +1,12 @@ use parking_lot::ReentrantMutex; -use std::cell::{RefCell, UnsafeCell}; +use std::cell::UnsafeCell; use std::ffi::{CStr, CString}; use std::ops::Drop; use std::path::PathBuf; use std::ptr; -use std::rc::Rc; use crate::clipboard::{ClipboardBackend, ClipboardContext}; -use crate::fonts::atlas::{FontAtlas, FontAtlasRefMut, FontId, SharedFontAtlas}; +use crate::fonts::atlas::{FontAtlas, FontId, SharedFontAtlas}; use crate::io::Io; use crate::style::Style; use crate::Ui; @@ -50,7 +49,7 @@ use crate::{sys, DrawData}; #[derive(Debug)] pub struct Context { raw: *mut sys::ImGuiContext, - shared_font_atlas: Option>>, + shared_font_atlas: Option>, ini_filename: Option, log_filename: Option, platform_name: Option, @@ -94,7 +93,7 @@ impl Context { /// /// Panics if an active context already exists #[doc(alias = "CreateContext")] - pub fn create_with_shared_font_atlas(shared_font_atlas: Rc>) -> Self { + pub fn create_with_shared_font_atlas(shared_font_atlas: UnsafeCell) -> Self { Self::create_internal(Some(shared_font_atlas)) } /// Suspends this context so another context can be the active context. @@ -217,7 +216,7 @@ impl Context { io.clipboard_user_data = clipboard_ctx.get() as *mut _; self.clipboard_ctx = clipboard_ctx; } - fn create_internal(shared_font_atlas: Option>>) -> Self { + fn create_internal(shared_font_atlas: Option>) -> Self { let _guard = CTX_MUTEX.lock(); assert!( no_current_context(), @@ -226,8 +225,8 @@ impl Context { let shared_font_atlas_ptr = match &shared_font_atlas { Some(shared_font_atlas) => { - let borrowed_font_atlas = shared_font_atlas.borrow(); - borrowed_font_atlas.0 + let borrowed_font_atlas = shared_font_atlas.get(); + unsafe { &*borrowed_font_atlas }.0 } None => ptr::null_mut(), }; @@ -243,7 +242,9 @@ impl Context { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), - ui: Ui(().into()), + ui: Ui { + buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)), + }, } } fn is_current_context(&self) -> bool { @@ -297,7 +298,7 @@ impl SuspendedContext { Self::create_internal(None) } /// Creates a new suspended imgui-rs context with a shared font atlas. - pub fn create_with_shared_font_atlas(shared_font_atlas: Rc>) -> Self { + pub fn create_with_shared_font_atlas(shared_font_atlas: UnsafeCell) -> Self { Self::create_internal(Some(shared_font_atlas)) } /// Attempts to activate this suspended context. @@ -318,7 +319,7 @@ impl SuspendedContext { Err(self) } } - fn create_internal(shared_font_atlas: Option>>) -> Self { + fn create_internal(shared_font_atlas: Option>) -> Self { let _guard = CTX_MUTEX.lock(); let raw = unsafe { sys::igCreateContext(ptr::null_mut()) }; let ctx = Context { @@ -329,7 +330,9 @@ impl SuspendedContext { platform_name: None, renderer_name: None, clipboard_ctx: Box::new(ClipboardContext::dummy().into()), - ui: Ui(().into()), + ui: Ui { + buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)), + }, }; if ctx.is_current_context() { // Oops, the context was activated -> deactivate @@ -411,9 +414,9 @@ fn test_suspend_failure() { #[test] fn test_shared_font_atlas() { let _guard = crate::test::TEST_MUTEX.lock(); - let atlas = Rc::new(RefCell::new(SharedFontAtlas::create())); - let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone()); - let mut ctx2 = Context::create_with_shared_font_atlas(atlas); + let atlas = SharedFontAtlas::create(); + let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone().into()); + let mut ctx2 = Context::create_with_shared_font_atlas(atlas.into()); { let _borrow = ctx2.fonts(); } @@ -422,17 +425,6 @@ fn test_shared_font_atlas() { let _borrow = ctx.fonts(); } -#[test] -#[should_panic] -fn test_shared_font_atlas_borrow_panic() { - let _guard = crate::test::TEST_MUTEX.lock(); - let atlas = Rc::new(RefCell::new(SharedFontAtlas::create())); - let _suspended = SuspendedContext::create_with_shared_font_atlas(atlas.clone()); - let mut ctx = Context::create_with_shared_font_atlas(atlas.clone()); - let _borrow1 = atlas.borrow(); - let _borrow2 = ctx.fonts(); -} - #[test] fn test_ini_load_save() { let (_guard, mut ctx) = crate::test::test_ctx(); @@ -506,19 +498,11 @@ impl Context { } } /// Returns a mutable reference to the font atlas. - /// - /// # Panics - /// - /// Panics if the context uses a shared font atlas that is already borrowed - pub fn fonts(&mut self) -> FontAtlasRefMut<'_> { - match self.shared_font_atlas { - Some(ref font_atlas) => FontAtlasRefMut::Shared(font_atlas.borrow_mut()), - None => unsafe { - // safe because FontAtlas is a transparent wrapper around sys::ImFontAtlas - let fonts = &mut *(self.io_mut().fonts as *mut FontAtlas); - FontAtlasRefMut::Owned(fonts) - }, - } + pub fn fonts(&mut self) -> &mut FontAtlas { + // we take this with an `&mut Self` here, which means + // that we can't get the sharedfontatlas through safe code + // otherwise + unsafe { &mut *(self.io_mut().fonts as *mut FontAtlas) } } /// Starts a new frame. @@ -539,10 +523,6 @@ impl Context { if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() { self.io_mut().font_default = ptr::null_mut(); } - // NewFrame/Render/EndFrame mutate the font atlas so we need exclusive access to it - if let Some(font_atlas) = self.shared_font_atlas.as_ref() { - assert!(font_atlas.try_borrow_mut().is_ok()); - } // TODO: precondition checks unsafe { sys::igNewFrame(); diff --git a/imgui/src/fonts/atlas.rs b/imgui/src/fonts/atlas.rs index 708b494..e1a8152 100644 --- a/imgui/src/fonts/atlas.rs +++ b/imgui/src/fonts/atlas.rs @@ -433,7 +433,7 @@ pub struct FontAtlasTexture<'a> { } /// A font atlas that can be shared between contexts -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SharedFontAtlas(pub(crate) *mut sys::ImFontAtlas); impl SharedFontAtlas { diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index f6338cf..ef2cb3b 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -116,15 +116,12 @@ impl Context { } } -/// A temporary reference for building the user interface for one frame +/// A reference for building the user interface for one frame #[derive(Debug)] -pub struct Ui(pub(crate) cell::UnsafeCell<()>); - -/// This is our internal buffer that we use for the Ui object. -/// -/// We edit this buffer -static mut BUFFER: cell::UnsafeCell = - cell::UnsafeCell::new(string::UiBuffer::new(100)); +pub struct Ui { + // our scratch sheet + buffer: cell::UnsafeCell, +} impl Ui { /// This provides access to the backing scratch buffer that we use to write @@ -141,13 +138,13 @@ impl Ui { /// We otherwise make no assumptions about the size or keep state in this buffer between calls, /// so editing the `UiBuffer` is fine. pub unsafe fn scratch_buffer(&self) -> &cell::UnsafeCell { - &BUFFER + &self.buffer } /// Internal method to push a single text to our scratch buffer. fn scratch_txt(&self, txt: impl AsRef) -> *const sys::cty::c_char { unsafe { - let handle = &mut *BUFFER.get(); + let handle = &mut *self.buffer.get(); handle.scratch_txt(txt) } } @@ -155,7 +152,7 @@ impl Ui { /// Internal method to push an option text to our scratch buffer. fn scratch_txt_opt(&self, txt: Option>) -> *const sys::cty::c_char { unsafe { - let handle = &mut *BUFFER.get(); + let handle = &mut *self.buffer.get(); handle.scratch_txt_opt(txt) } } @@ -166,7 +163,7 @@ impl Ui { txt_1: impl AsRef, ) -> (*const sys::cty::c_char, *const sys::cty::c_char) { unsafe { - let handle = &mut *BUFFER.get(); + let handle = &mut *self.buffer.get(); handle.scratch_txt_two(txt_0, txt_1) } } @@ -177,7 +174,7 @@ impl Ui { txt_1: Option>, ) -> (*const sys::cty::c_char, *const sys::cty::c_char) { unsafe { - let handle = &mut *BUFFER.get(); + let handle = &mut *self.buffer.get(); handle.scratch_txt_with_opt(txt_0, txt_1) } } From 5bdd4f819cfff86e714c1909f42f05e1f11df0e9 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Tue, 28 Sep 2021 11:27:14 -0400 Subject: [PATCH 09/12] added end frame handle --- imgui/src/context.rs | 9 +++------ imgui/src/lib.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index 3acda71..c1a891e 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -505,17 +505,14 @@ impl Context { unsafe { &mut *(self.io_mut().fonts as *mut FontAtlas) } } - /// Starts a new frame. + /// Starts a new frame. Use [`new_frame`] instead. + /// + /// [`new_frame`]: Self::new_frame pub fn frame(&mut self) -> &mut Ui { self.new_frame() } /// Starts a new frame and returns an `Ui` instance for constructing a user interface. - /// - /// # Panics - /// - /// Panics if the context uses a shared font atlas that is already borrowed. - /// Do not attempt to borrow the context afterwards, if you are using a shared font atlas. #[doc(alias = "NewFame")] pub fn new_frame(&mut self) -> &mut Ui { // Clear default font if it no longer exists. This could be an error in the future diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index ef2cb3b..dc126d5 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -119,7 +119,7 @@ impl Context { /// A reference for building the user interface for one frame #[derive(Debug)] pub struct Ui { - // our scratch sheet + /// our scratch sheet buffer: cell::UnsafeCell, } @@ -189,10 +189,36 @@ impl Ui { pub fn fonts(&self) -> &FontAtlas { unsafe { &*(self.io().fonts as *const FontAtlas) } } + /// Returns a clone of the user interface style pub fn clone_style(&self) -> Style { unsafe { *self.style() } } + + /// This function, and the library's api, has been changed as of `0.9`! + /// Do not use this function! Instead, use [`Context::render`], + /// which does what this function in `0.8` used to do. + /// + /// This function right now simply **ends** the current frame, but does not + /// return draw data. If you want to end the frame without generated draw data, + /// and thus save some CPU time, use [`end_frame_early`]. + #[deprecated( + since = "0.9.0", + note = "use `Context::render` to render frames, or `end_frame_early` to not render at all" + )] + pub fn render(&mut self) { + self.end_frame_early(); + } + + /// Use this function to end the frame early. + /// After this call, you should **stop using the `Ui` object till `new_frame` has been called.** + /// + /// You probably *don't want this function.* If you want to render your data, use `Context::render` now. + pub fn end_frame_early(&mut self) { + unsafe { + sys::igEndFrame(); + } + } } /// # Demo, debug, information From 76c74fbfc5177326b65ef1a221daa04221147916 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Thu, 30 Sep 2021 18:33:00 -0400 Subject: [PATCH 10/12] quick fix --- imgui-glium-renderer/src/lib.rs | 2 +- imgui-glow-renderer/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui-glium-renderer/src/lib.rs b/imgui-glium-renderer/src/lib.rs index 723fae9..eddc659 100644 --- a/imgui-glium-renderer/src/lib.rs +++ b/imgui-glium-renderer/src/lib.rs @@ -276,7 +276,7 @@ impl Renderer { } fn upload_font_texture( - mut fonts: imgui::FontAtlasRefMut, + fonts: &mut imgui::FontAtlas, ctx: &Rc, ) -> Result { let texture = fonts.build_rgba32_texture(); diff --git a/imgui-glow-renderer/src/lib.rs b/imgui-glow-renderer/src/lib.rs index eacdd90..87fd214 100644 --- a/imgui-glow-renderer/src/lib.rs +++ b/imgui-glow-renderer/src/lib.rs @@ -1042,7 +1042,7 @@ pub type RenderError = String; fn prepare_font_atlas( gl: &Context, - mut fonts: imgui::FontAtlasRefMut, + fonts: &mut imgui::FontAtlas, texture_map: &mut T, ) -> Result { #![allow(clippy::cast_possible_wrap)] From 1f65184deb0cca1c1cb160d20f3abf2598d1a919 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Fri, 1 Oct 2021 12:33:36 -0400 Subject: [PATCH 11/12] borked the lifetime, simplified here --- imgui/src/context.rs | 22 +++---- imgui/src/fonts/atlas.rs | 134 ++++++++++++++++++++++----------------- 2 files changed, 86 insertions(+), 70 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index c1a891e..95c971e 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -49,7 +49,7 @@ use crate::{sys, DrawData}; #[derive(Debug)] pub struct Context { raw: *mut sys::ImGuiContext, - shared_font_atlas: Option>, + shared_font_atlas: Option, ini_filename: Option, log_filename: Option, platform_name: Option, @@ -93,7 +93,7 @@ impl Context { /// /// Panics if an active context already exists #[doc(alias = "CreateContext")] - pub fn create_with_shared_font_atlas(shared_font_atlas: UnsafeCell) -> Self { + pub fn create_with_shared_font_atlas(shared_font_atlas: SharedFontAtlas) -> Self { Self::create_internal(Some(shared_font_atlas)) } /// Suspends this context so another context can be the active context. @@ -216,18 +216,15 @@ impl Context { io.clipboard_user_data = clipboard_ctx.get() as *mut _; self.clipboard_ctx = clipboard_ctx; } - fn create_internal(shared_font_atlas: Option>) -> Self { + fn create_internal(mut shared_font_atlas: Option) -> Self { let _guard = CTX_MUTEX.lock(); assert!( no_current_context(), "A new active context cannot be created, because another one already exists" ); - let shared_font_atlas_ptr = match &shared_font_atlas { - Some(shared_font_atlas) => { - let borrowed_font_atlas = shared_font_atlas.get(); - unsafe { &*borrowed_font_atlas }.0 - } + let shared_font_atlas_ptr = match &mut shared_font_atlas { + Some(shared_font_atlas) => shared_font_atlas.as_ptr_mut(), None => ptr::null_mut(), }; // Dear ImGui implicitly sets the current context during igCreateContext if the current @@ -297,8 +294,9 @@ impl SuspendedContext { pub fn create() -> Self { Self::create_internal(None) } + /// Creates a new suspended imgui-rs context with a shared font atlas. - pub fn create_with_shared_font_atlas(shared_font_atlas: UnsafeCell) -> Self { + pub fn create_with_shared_font_atlas(shared_font_atlas: SharedFontAtlas) -> Self { Self::create_internal(Some(shared_font_atlas)) } /// Attempts to activate this suspended context. @@ -319,7 +317,7 @@ impl SuspendedContext { Err(self) } } - fn create_internal(shared_font_atlas: Option>) -> Self { + fn create_internal(shared_font_atlas: Option) -> Self { let _guard = CTX_MUTEX.lock(); let raw = unsafe { sys::igCreateContext(ptr::null_mut()) }; let ctx = Context { @@ -415,8 +413,8 @@ fn test_suspend_failure() { fn test_shared_font_atlas() { let _guard = crate::test::TEST_MUTEX.lock(); let atlas = SharedFontAtlas::create(); - let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone().into()); - let mut ctx2 = Context::create_with_shared_font_atlas(atlas.into()); + let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone()); + let mut ctx2 = Context::create_with_shared_font_atlas(atlas); { let _borrow = ctx2.fonts(); } diff --git a/imgui/src/fonts/atlas.rs b/imgui/src/fonts/atlas.rs index e1a8152..a3f438b 100644 --- a/imgui/src/fonts/atlas.rs +++ b/imgui/src/fonts/atlas.rs @@ -1,9 +1,8 @@ use bitflags::bitflags; -use std::cell; use std::f32; -use std::ops::{Deref, DerefMut}; use std::os::raw::{c_int, c_uchar, c_void}; use std::ptr; +use std::rc::Rc; use std::slice; use crate::fonts::font::Font; @@ -434,75 +433,94 @@ pub struct FontAtlasTexture<'a> { /// A font atlas that can be shared between contexts #[derive(Debug, Clone)] -pub struct SharedFontAtlas(pub(crate) *mut sys::ImFontAtlas); +pub struct SharedFontAtlas(pub(crate) Rc<*mut sys::ImFontAtlas>); + +impl std::ops::Deref for SharedFontAtlas { + type Target = Rc<*mut sys::ImFontAtlas>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for SharedFontAtlas { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} impl SharedFontAtlas { #[doc(alias = "ImFontAtlas", alias = "ImFontAtlas::ImFontAtlas")] pub fn create() -> SharedFontAtlas { - SharedFontAtlas(unsafe { sys::ImFontAtlas_ImFontAtlas() }) + SharedFontAtlas(unsafe { Rc::new(sys::ImFontAtlas_ImFontAtlas()) }) + } + + /// Gets a raw pointer to the underlying `ImFontAtlas`. + pub fn as_ptr(&self) -> *const sys::ImFontAtlas { + *self.0 as *const _ + } + + /// Gets a raw pointer to the underlying `ImFontAtlas`. + pub fn as_ptr_mut(&mut self) -> *mut sys::ImFontAtlas { + *self.0 } } impl Drop for SharedFontAtlas { #[doc(alias = "ImFontAtlas::Destory")] fn drop(&mut self) { - unsafe { sys::ImFontAtlas_destroy(self.0) }; - } -} - -impl Deref for SharedFontAtlas { - type Target = FontAtlas; - fn deref(&self) -> &FontAtlas { - unsafe { &*(self.0 as *const FontAtlas) } - } -} - -impl DerefMut for SharedFontAtlas { - fn deref_mut(&mut self) -> &mut FontAtlas { - unsafe { &mut *(self.0 as *mut FontAtlas) } - } -} - -/// An immutably borrowed reference to a (possibly shared) font atlas -pub enum FontAtlasRef<'a> { - Owned(&'a FontAtlas), - Shared(&'a cell::RefMut<'a, SharedFontAtlas>), -} - -impl<'a> Deref for FontAtlasRef<'a> { - type Target = FontAtlas; - fn deref(&self) -> &FontAtlas { - use self::FontAtlasRef::*; - match self { - Owned(atlas) => atlas, - Shared(cell) => cell, + // if we're about to drop the last one... + if Rc::strong_count(&self.0) == 1 { + unsafe { sys::ImFontAtlas_destroy(*self.0) }; } } } -/// A mutably borrowed reference to a (possibly shared) font atlas -pub enum FontAtlasRefMut<'a> { - Owned(&'a mut FontAtlas), - Shared(cell::RefMut<'a, SharedFontAtlas>), -} +// /// An immutably borrowed reference to a (possibly shared) font atlas +// pub enum FontAtlasRef<'a> { +// Owned(&'a FontAtlas), +// Shared(&'a cell::RefMut<'a, SharedFontAtlas>), +// } -impl<'a> Deref for FontAtlasRefMut<'a> { - type Target = FontAtlas; - fn deref(&self) -> &FontAtlas { - use self::FontAtlasRefMut::*; - match self { - Owned(atlas) => atlas, - Shared(cell) => cell, - } - } -} +// impl<'a> Deref for FontAtlasRef<'a> { +// type Target = FontAtlas; +// fn deref(&self) -> &FontAtlas { +// use self::FontAtlasRef::*; +// match self { +// Owned(atlas) => atlas, +// Shared(cell) => { +// let font_atlas: &SharedFontAtlas = &cell; +// let font_atlas: &FontAtlas = &font_atlas; -impl<'a> DerefMut for FontAtlasRefMut<'a> { - fn deref_mut(&mut self) -> &mut FontAtlas { - use self::FontAtlasRefMut::*; - match self { - Owned(atlas) => atlas, - Shared(cell) => cell, - } - } -} +// todo!() +// } +// } +// } +// } + +// /// A mutably borrowed reference to a (possibly shared) font atlas +// pub enum FontAtlasRefMut<'a> { +// Owned(&'a mut FontAtlas), +// Shared(cell::RefMut<'a, SharedFontAtlas>), +// } + +// impl<'a> Deref for FontAtlasRefMut<'a> { +// type Target = FontAtlas; +// fn deref(&self) -> &FontAtlas { +// use self::FontAtlasRefMut::*; +// match self { +// Owned(atlas) => atlas, +// Shared(cell) => cell, +// } +// } +// } + +// impl<'a> DerefMut for FontAtlasRefMut<'a> { +// fn deref_mut(&mut self) -> &mut FontAtlas { +// use self::FontAtlasRefMut::*; +// match self { +// Owned(atlas) => atlas, +// Shared(cell) => cell, +// } +// } +// } From 5a9827094492a80202650cf4b1f5f02b5cf10cf5 Mon Sep 17 00:00:00 2001 From: Jack Mac Date: Fri, 1 Oct 2021 12:35:22 -0400 Subject: [PATCH 12/12] added clone so i guess you can interact with it here... --- imgui/src/context.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index 95c971e..19afb28 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -503,6 +503,11 @@ impl Context { unsafe { &mut *(self.io_mut().fonts as *mut FontAtlas) } } + /// Attempts to clone the interior shared font atlas **if it exists**. + pub fn clone_shared_font_atlas(&mut self) -> Option { + self.shared_font_atlas.clone() + } + /// Starts a new frame. Use [`new_frame`] instead. /// /// [`new_frame`]: Self::new_frame