From 52898779e1e8e28f7cc2daa444a8c50fde81f6eb Mon Sep 17 00:00:00 2001 From: dbr Date: Mon, 13 Sep 2021 18:22:51 +1000 Subject: [PATCH 1/2] Allow simultaneous access to different draw lists Only need to prevent accessing the same draw-list twice at one time Closes #488 --- imgui-examples/examples/draw_list.rs | 12 ++++++-- imgui/src/draw_list.rs | 45 +++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/imgui-examples/examples/draw_list.rs b/imgui-examples/examples/draw_list.rs index 716f959..a54698a 100644 --- a/imgui-examples/examples/draw_list.rs +++ b/imgui-examples/examples/draw_list.rs @@ -19,8 +19,17 @@ fn draw_text_centered( fn main() { let system = support::init(file!()); system.main_loop(move |_, ui| { + + // Get access to draw FG and BG draw lists. + let bg_draw_list = ui.get_background_draw_list(); + let fg_draw_list = ui.get_foreground_draw_list(); + + // Note we cannot access two instances of the same draw list + // at once. That is to say, the following line would panic if + // uncommented: + //let bg_draw_list_2 = ui.get_background_draw_list(); // panic! + { - let bg_draw_list = ui.get_background_draw_list(); bg_draw_list .add_circle([150.0, 150.0], 150.0, [1.0, 0.0, 0.0]) .thickness(4.0) @@ -36,7 +45,6 @@ fn main() { { let [w, h] = ui.io().display_size; - let fg_draw_list = ui.get_foreground_draw_list(); fg_draw_list .add_circle([w - 150.0, h - 150.0], 150.0, [1.0, 0.0, 0.0]) .thickness(4.0) diff --git a/imgui/src/draw_list.rs b/imgui/src/draw_list.rs index 4545675..b0b7a53 100644 --- a/imgui/src/draw_list.rs +++ b/imgui/src/draw_list.rs @@ -61,27 +61,47 @@ bitflags!( } ); +enum DrawListType { + Window, + Background, + Foreground, +} + /// Object implementing the custom draw API. /// /// Called from [`Ui::get_window_draw_list`], [`Ui::get_background_draw_list`] or [`Ui::get_foreground_draw_list`]. /// No more than one instance of this structure can live in a program at the same time. /// The program will panic on creating a second instance. pub struct DrawListMut<'ui> { + draw_list_type: DrawListType, draw_list: *mut ImDrawList, _phantom: PhantomData<&'ui Ui<'ui>>, } -static DRAW_LIST_LOADED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); +// Lock for each variant of draw list. See https://github.com/imgui-rs/imgui-rs/issues/488 +static DRAW_LIST_LOADED_WINDOW: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); +static DRAW_LIST_LOADED_BACKGROUND: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); +static DRAW_LIST_LOADED_FOREGROUND: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); impl<'ui> Drop for DrawListMut<'ui> { fn drop(&mut self) { - DRAW_LIST_LOADED.store(false, std::sync::atomic::Ordering::Release); + match self.draw_list_type { + DrawListType::Window => &DRAW_LIST_LOADED_WINDOW, + DrawListType::Background => &DRAW_LIST_LOADED_BACKGROUND, + DrawListType::Foreground => &DRAW_LIST_LOADED_FOREGROUND, + }.store(false, std::sync::atomic::Ordering::Release); } } impl<'ui> DrawListMut<'ui> { - fn lock_draw_list() { - let already_loaded = DRAW_LIST_LOADED + fn lock_draw_list(t: DrawListType) { + let lock = match t { + DrawListType::Window => &DRAW_LIST_LOADED_WINDOW, + DrawListType::Background => &DRAW_LIST_LOADED_BACKGROUND, + DrawListType::Foreground => &DRAW_LIST_LOADED_FOREGROUND, + }; + + let already_loaded = lock .compare_exchange( false, true, @@ -90,33 +110,42 @@ impl<'ui> DrawListMut<'ui> { ) .is_err(); if already_loaded { - panic!("DrawListMut is already loaded! You can only load one instance of it!") + let name = match t { + DrawListType::Window => "window", + DrawListType::Background => "background", + DrawListType::Foreground => "foreground", + }; + panic!("The DrawListMut instance for the {} draw list is already loaded! You can only load one instance of it!", name) } } #[doc(alias = "GetWindowDrawList")] pub(crate) fn window(_: &Ui<'ui>) -> Self { - Self::lock_draw_list(); + Self::lock_draw_list(DrawListType::Window); + Self { draw_list: unsafe { sys::igGetWindowDrawList() }, + draw_list_type: DrawListType::Window, _phantom: PhantomData, } } #[doc(alias = "GetBackgroundDrawList")] pub(crate) fn background(_: &Ui<'ui>) -> Self { - Self::lock_draw_list(); + Self::lock_draw_list(DrawListType::Background); Self { draw_list: unsafe { sys::igGetBackgroundDrawList() }, + draw_list_type: DrawListType::Background, _phantom: PhantomData, } } #[doc(alias = "GetForegroundDrawList")] pub(crate) fn foreground(_: &Ui<'ui>) -> Self { - Self::lock_draw_list(); + Self::lock_draw_list(DrawListType::Foreground); Self { draw_list: unsafe { sys::igGetForegroundDrawList() }, + draw_list_type: DrawListType::Foreground, _phantom: PhantomData, } } From 0784c95f298a65f06c58bf2b751c11e6e762d901 Mon Sep 17 00:00:00 2001 From: dbr Date: Mon, 13 Sep 2021 18:24:38 +1000 Subject: [PATCH 2/2] fmt --- imgui-examples/examples/draw_list.rs | 1 - imgui/src/draw_list.rs | 12 ++++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui-examples/examples/draw_list.rs b/imgui-examples/examples/draw_list.rs index a54698a..9d1a5b2 100644 --- a/imgui-examples/examples/draw_list.rs +++ b/imgui-examples/examples/draw_list.rs @@ -19,7 +19,6 @@ fn draw_text_centered( fn main() { let system = support::init(file!()); system.main_loop(move |_, ui| { - // Get access to draw FG and BG draw lists. let bg_draw_list = ui.get_background_draw_list(); let fg_draw_list = ui.get_foreground_draw_list(); diff --git a/imgui/src/draw_list.rs b/imgui/src/draw_list.rs index b0b7a53..a94c36e 100644 --- a/imgui/src/draw_list.rs +++ b/imgui/src/draw_list.rs @@ -79,9 +79,12 @@ pub struct DrawListMut<'ui> { } // Lock for each variant of draw list. See https://github.com/imgui-rs/imgui-rs/issues/488 -static DRAW_LIST_LOADED_WINDOW: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); -static DRAW_LIST_LOADED_BACKGROUND: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); -static DRAW_LIST_LOADED_FOREGROUND: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); +static DRAW_LIST_LOADED_WINDOW: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); +static DRAW_LIST_LOADED_BACKGROUND: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); +static DRAW_LIST_LOADED_FOREGROUND: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); impl<'ui> Drop for DrawListMut<'ui> { fn drop(&mut self) { @@ -89,7 +92,8 @@ impl<'ui> Drop for DrawListMut<'ui> { DrawListType::Window => &DRAW_LIST_LOADED_WINDOW, DrawListType::Background => &DRAW_LIST_LOADED_BACKGROUND, DrawListType::Foreground => &DRAW_LIST_LOADED_FOREGROUND, - }.store(false, std::sync::atomic::Ordering::Release); + } + .store(false, std::sync::atomic::Ordering::Release); } }