mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-11 13:38:35 +00:00
Refactor WindowDrawList into DrawListMut and fix #413.
- Rename WindowDrawList -> DrawListMut. It's not about window draw lists, but about background/foreground draw lists as well. The naming was not an easy choice, but seems like in rust it's a common convention to add a Mut suffix for mutable entities. Imgui-rs already has DrawList and it acts as an immutable reference type for rendering implementations to consume. Hence the name DrawListMut, which becomes a mutable reference to draw list with methods to modify it. - Add Ui::get_foreground_draw_list(). Same as Ui::get_background_draw_list() but for foreground. - Add draw_list example which shows the use of all three draw lists (window, bg, fg).
This commit is contained in:
parent
81e21f5853
commit
171d86aea1
90
imgui-examples/examples/draw_list.rs
Normal file
90
imgui-examples/examples/draw_list.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use imgui::*;
|
||||
|
||||
mod support;
|
||||
|
||||
// rect is [x, y, w, h]
|
||||
fn draw_text_centered(
|
||||
ui: &Ui,
|
||||
draw_list: &DrawListMut,
|
||||
rect: [f32; 4],
|
||||
text: &ImStr,
|
||||
color: [f32; 3],
|
||||
) {
|
||||
let text_size = ui.calc_text_size(text, false, 0.0);
|
||||
let cx = (rect[2] - text_size[0]) / 2.0;
|
||||
let cy = (rect[3] - text_size[1]) / 2.0;
|
||||
draw_list.add_text([rect[0] + cx, rect[1] + cy], color, text);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let system = support::init(file!());
|
||||
system.main_loop(move |_, ui| {
|
||||
{
|
||||
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)
|
||||
.build();
|
||||
draw_text_centered(
|
||||
ui,
|
||||
&bg_draw_list,
|
||||
[0.0, 0.0, 300.0, 300.0],
|
||||
im_str!("background draw list"),
|
||||
[0.0, 0.0, 0.0],
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
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)
|
||||
.build();
|
||||
draw_text_centered(
|
||||
ui,
|
||||
&fg_draw_list,
|
||||
[w - 300.0, h - 300.0, 300.0, 300.0],
|
||||
im_str!("foreground draw list"),
|
||||
[1.0, 0.0, 0.0],
|
||||
);
|
||||
}
|
||||
|
||||
Window::new(im_str!("Draw list"))
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.scroll_bar(false)
|
||||
.build(ui, || {
|
||||
ui.button(im_str!("random button"), [0.0, 0.0]);
|
||||
let draw_list = ui.get_window_draw_list();
|
||||
let o = ui.cursor_screen_pos();
|
||||
let ws = ui.content_region_avail();
|
||||
draw_list
|
||||
.add_circle([o[0] + 10.0, o[1] + 10.0], 5.0, [1.0, 0.0, 0.0])
|
||||
.thickness(4.0)
|
||||
.build();
|
||||
draw_list
|
||||
.add_circle([o[0] + ws[0] - 10.0, o[1] + 10.0], 5.0, [0.0, 1.0, 0.0])
|
||||
.thickness(4.0)
|
||||
.build();
|
||||
draw_list
|
||||
.add_circle(
|
||||
[o[0] + ws[0] - 10.0, o[1] + ws[1] - 10.0],
|
||||
5.0,
|
||||
[0.0, 0.0, 1.0],
|
||||
)
|
||||
.thickness(4.0)
|
||||
.build();
|
||||
draw_list
|
||||
.add_circle([o[0] + 10.0, o[1] + ws[1] - 10.0], 5.0, [1.0, 1.0, 0.0])
|
||||
.thickness(4.0)
|
||||
.build();
|
||||
draw_text_centered(
|
||||
ui,
|
||||
&draw_list,
|
||||
[o[0], o[1], ws[0], ws[1]],
|
||||
im_str!("window draw list"),
|
||||
[1.0, 1.0, 1.0],
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -53,26 +53,25 @@ impl From<(f32, f32, f32)> for ImColor {
|
||||
|
||||
/// Object implementing the custom draw API.
|
||||
///
|
||||
/// Called from [`Ui::get_window_draw_list`]. No more than one instance of this
|
||||
/// structure can live in a program at the same time.
|
||||
/// 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 WindowDrawList<'ui> {
|
||||
pub struct DrawListMut<'ui> {
|
||||
draw_list: *mut ImDrawList,
|
||||
_phantom: PhantomData<&'ui Ui<'ui>>,
|
||||
}
|
||||
|
||||
static WINDOW_DRAW_LIST_LOADED: std::sync::atomic::AtomicBool =
|
||||
std::sync::atomic::AtomicBool::new(false);
|
||||
static DRAW_LIST_LOADED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
impl<'ui> Drop for WindowDrawList<'ui> {
|
||||
impl<'ui> Drop for DrawListMut<'ui> {
|
||||
fn drop(&mut self) {
|
||||
WINDOW_DRAW_LIST_LOADED.store(false, std::sync::atomic::Ordering::Release);
|
||||
DRAW_LIST_LOADED.store(false, std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ui> WindowDrawList<'ui> {
|
||||
pub(crate) fn new(_: &Ui<'ui>) -> Self {
|
||||
let already_loaded = WINDOW_DRAW_LIST_LOADED
|
||||
impl<'ui> DrawListMut<'ui> {
|
||||
fn lock_draw_list() {
|
||||
let already_loaded = DRAW_LIST_LOADED
|
||||
.compare_exchange(
|
||||
false,
|
||||
true,
|
||||
@ -81,21 +80,34 @@ impl<'ui> WindowDrawList<'ui> {
|
||||
)
|
||||
.is_err();
|
||||
if already_loaded {
|
||||
panic!("WindowDrawList is already loaded! You can only load one instance of it!")
|
||||
panic!("DrawListMut is already loaded! You can only load one instance of it!")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn window(_: &Ui<'ui>) -> Self {
|
||||
Self::lock_draw_list();
|
||||
Self {
|
||||
draw_list: unsafe { sys::igGetWindowDrawList() },
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn background(self) -> Self {
|
||||
pub(crate) fn background(_: &Ui<'ui>) -> Self {
|
||||
Self::lock_draw_list();
|
||||
Self {
|
||||
draw_list: unsafe { sys::igGetBackgroundDrawList() },
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn foreground(_: &Ui<'ui>) -> Self {
|
||||
Self::lock_draw_list();
|
||||
Self {
|
||||
draw_list: unsafe { sys::igGetForegroundDrawList() },
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Split into *channels_count* drawing channels.
|
||||
/// At the end of the closure, the channels are merged. The objects
|
||||
/// are then drawn in the increasing order of their channel number, and not
|
||||
@ -127,9 +139,9 @@ impl<'ui> WindowDrawList<'ui> {
|
||||
|
||||
/// Represent the drawing interface within a call to [`channels_split`].
|
||||
///
|
||||
/// [`channels_split`]: WindowDrawList::channels_split
|
||||
/// [`channels_split`]: DrawListMut::channels_split
|
||||
pub struct ChannelsSplit<'ui> {
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
channels_count: u32,
|
||||
}
|
||||
|
||||
@ -151,7 +163,7 @@ impl<'ui> ChannelsSplit<'ui> {
|
||||
}
|
||||
|
||||
/// Drawing functions
|
||||
impl<'ui> WindowDrawList<'ui> {
|
||||
impl<'ui> DrawListMut<'ui> {
|
||||
/// Returns a line from point `p1` to `p2` with color `c`.
|
||||
pub fn add_line<C>(&'ui self, p1: [f32; 2], p2: [f32; 2], c: C) -> Line<'ui>
|
||||
where
|
||||
@ -291,11 +303,11 @@ pub struct Line<'ui> {
|
||||
p2: [f32; 2],
|
||||
color: ImColor,
|
||||
thickness: f32,
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
}
|
||||
|
||||
impl<'ui> Line<'ui> {
|
||||
fn new<C>(draw_list: &'ui WindowDrawList, p1: [f32; 2], p2: [f32; 2], c: C) -> Self
|
||||
fn new<C>(draw_list: &'ui DrawListMut, p1: [f32; 2], p2: [f32; 2], c: C) -> Self
|
||||
where
|
||||
C: Into<ImColor>,
|
||||
{
|
||||
@ -338,11 +350,11 @@ pub struct Rect<'ui> {
|
||||
flags: ImDrawCornerFlags,
|
||||
thickness: f32,
|
||||
filled: bool,
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
}
|
||||
|
||||
impl<'ui> Rect<'ui> {
|
||||
fn new<C>(draw_list: &'ui WindowDrawList, p1: [f32; 2], p2: [f32; 2], c: C) -> Self
|
||||
fn new<C>(draw_list: &'ui DrawListMut, p1: [f32; 2], p2: [f32; 2], c: C) -> Self
|
||||
where
|
||||
C: Into<ImColor>,
|
||||
{
|
||||
@ -439,17 +451,11 @@ pub struct Triangle<'ui> {
|
||||
color: ImColor,
|
||||
thickness: f32,
|
||||
filled: bool,
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
}
|
||||
|
||||
impl<'ui> Triangle<'ui> {
|
||||
fn new<C>(
|
||||
draw_list: &'ui WindowDrawList,
|
||||
p1: [f32; 2],
|
||||
p2: [f32; 2],
|
||||
p3: [f32; 2],
|
||||
c: C,
|
||||
) -> Self
|
||||
fn new<C>(draw_list: &'ui DrawListMut, p1: [f32; 2], p2: [f32; 2], p3: [f32; 2], c: C) -> Self
|
||||
where
|
||||
C: Into<ImColor>,
|
||||
{
|
||||
@ -512,11 +518,11 @@ pub struct Circle<'ui> {
|
||||
num_segments: u32,
|
||||
thickness: f32,
|
||||
filled: bool,
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
}
|
||||
|
||||
impl<'ui> Circle<'ui> {
|
||||
pub fn new<C>(draw_list: &'ui WindowDrawList, center: [f32; 2], radius: f32, color: C) -> Self
|
||||
pub fn new<C>(draw_list: &'ui DrawListMut, center: [f32; 2], radius: f32, color: C) -> Self
|
||||
where
|
||||
C: Into<ImColor>,
|
||||
{
|
||||
@ -588,12 +594,12 @@ pub struct BezierCurve<'ui> {
|
||||
thickness: f32,
|
||||
/// If num_segments is not set, the bezier curve is auto-tessalated.
|
||||
num_segments: Option<u32>,
|
||||
draw_list: &'ui WindowDrawList<'ui>,
|
||||
draw_list: &'ui DrawListMut<'ui>,
|
||||
}
|
||||
|
||||
impl<'ui> BezierCurve<'ui> {
|
||||
fn new<C>(
|
||||
draw_list: &'ui WindowDrawList,
|
||||
draw_list: &'ui DrawListMut,
|
||||
pos0: [f32; 2],
|
||||
cp0: [f32; 2],
|
||||
cp1: [f32; 2],
|
||||
@ -10,6 +10,7 @@ use std::thread;
|
||||
|
||||
pub use self::clipboard::*;
|
||||
pub use self::context::*;
|
||||
pub use self::draw_list::{ChannelsSplit, DrawListMut, ImColor};
|
||||
pub use self::fonts::atlas::*;
|
||||
pub use self::fonts::font::*;
|
||||
pub use self::fonts::glyph::*;
|
||||
@ -46,12 +47,12 @@ pub use self::widget::tab::*;
|
||||
pub use self::widget::tree::*;
|
||||
pub use self::window::child_window::*;
|
||||
pub use self::window::*;
|
||||
pub use self::window_draw_list::{ChannelsSplit, ImColor, WindowDrawList};
|
||||
use internal::RawCast;
|
||||
|
||||
mod clipboard;
|
||||
mod columns;
|
||||
mod context;
|
||||
mod draw_list;
|
||||
mod fonts;
|
||||
mod input;
|
||||
mod input_widget;
|
||||
@ -72,7 +73,6 @@ mod test;
|
||||
mod utils;
|
||||
mod widget;
|
||||
mod window;
|
||||
mod window_draw_list;
|
||||
|
||||
/// Returns the underlying Dear ImGui library version
|
||||
pub fn dear_imgui_version() -> &'static str {
|
||||
@ -470,7 +470,7 @@ impl<'ui> Ui<'ui> {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This function will panic if several instances of [`WindowDrawList`]
|
||||
/// This function will panic if several instances of [`DrawListMut`]
|
||||
/// coexist. Before a new instance is got, a previous instance should be
|
||||
/// dropped.
|
||||
///
|
||||
@ -485,13 +485,18 @@ impl<'ui> Ui<'ui> {
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn get_window_draw_list(&'ui self) -> WindowDrawList<'ui> {
|
||||
WindowDrawList::new(self)
|
||||
pub fn get_window_draw_list(&'ui self) -> DrawListMut<'ui> {
|
||||
DrawListMut::window(self)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_background_draw_list(&'ui self) -> WindowDrawList<'ui> {
|
||||
WindowDrawList::new(self).background()
|
||||
pub fn get_background_draw_list(&'ui self) -> DrawListMut<'ui> {
|
||||
DrawListMut::background(self)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_foreground_draw_list(&'ui self) -> DrawListMut<'ui> {
|
||||
DrawListMut::foreground(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user