dear_imgui_rs/draw/list/texture.rs
1use std::marker::PhantomData;
2
3use crate::sys;
4
5use super::DrawListMut;
6
7/// Tracks a texture pushed to a draw-list texture stack.
8///
9/// The texture is popped when the token is dropped or when [`Self::pop`] is
10/// called explicitly.
11#[must_use]
12pub struct DrawListTextureToken<'draw_list, 'tex> {
13 draw_list: *mut sys::ImDrawList,
14 _phantom: PhantomData<(&'draw_list (), &'tex mut crate::texture::TextureData)>,
15}
16
17impl<'draw_list, 'tex> DrawListTextureToken<'draw_list, 'tex> {
18 fn new(draw_list: *mut sys::ImDrawList) -> Self {
19 Self {
20 draw_list,
21 _phantom: PhantomData,
22 }
23 }
24
25 /// Pop the texture immediately instead of waiting for drop.
26 #[doc(alias = "PopTexture")]
27 pub fn pop(self) {}
28}
29
30impl Drop for DrawListTextureToken<'_, '_> {
31 fn drop(&mut self) {
32 unsafe { sys::ImDrawList_PopTexture(self.draw_list) }
33 }
34}
35
36impl<'ui> DrawListMut<'ui> {
37 // channels_split is provided on DrawListMut
38
39 /// Push a texture on the drawlist texture stack (ImGui 1.92+)
40 ///
41 /// While pushed, image and primitives will use this texture unless otherwise specified.
42 ///
43 /// Example:
44 /// ```no_run
45 /// # use dear_imgui_rs::*;
46 /// # fn demo(ui: &Ui) {
47 /// let dl = ui.get_window_draw_list();
48 /// let tex = texture::TextureId::new(1);
49 /// unsafe { dl.push_texture(tex) };
50 /// dl.add_image(tex, [10.0,10.0], [110.0,110.0], [0.0,0.0], [1.0,1.0], Color::WHITE);
51 /// dl.pop_texture();
52 /// # }
53 /// ```
54 #[doc(alias = "PushTexture")]
55 ///
56 /// # Safety
57 ///
58 /// The pushed texture reference remains on Dear ImGui's draw-list texture stack until
59 /// [`Self::pop_texture`] is called. If this is a managed texture reference, the referenced
60 /// texture data must remain valid until the stack entry is popped and any draw commands using it
61 /// have been consumed. Prefer [`Self::push_texture_token`] or [`Self::with_texture`] for scoped
62 /// safe usage.
63 pub unsafe fn push_texture<'tex>(&self, texture: impl Into<crate::texture::TextureRef<'tex>>) {
64 let tex_ref = texture.into().raw();
65 unsafe { sys::ImDrawList_PushTexture(self.draw_list, tex_ref) }
66 }
67
68 /// Push a texture on the draw-list texture stack and return an RAII token.
69 ///
70 /// Prefer this or [`Self::with_texture`] for scoped usage that remains
71 /// balanced if a panic unwinds through the scope. The manual
72 /// [`Self::push_texture`] / [`Self::pop_texture`] pair is kept for
73 /// compatibility with existing push/pop-style code.
74 #[doc(alias = "PushTexture")]
75 pub fn push_texture_token<'tex>(
76 &self,
77 texture: impl Into<crate::texture::TextureRef<'tex>>,
78 ) -> DrawListTextureToken<'_, 'tex> {
79 unsafe { self.push_texture(texture) };
80 DrawListTextureToken::new(self.draw_list)
81 }
82
83 /// Pop the last texture from the drawlist texture stack (ImGui 1.92+)
84 #[doc(alias = "PopTexture")]
85 pub fn pop_texture(&self) {
86 unsafe {
87 sys::ImDrawList_PopTexture(self.draw_list);
88 }
89 }
90
91 /// Push a texture, run `f`, then pop the texture.
92 ///
93 /// The texture is popped during unwinding if `f` panics.
94 #[doc(alias = "PushTexture", alias = "PopTexture")]
95 pub fn with_texture<'tex, R>(
96 &self,
97 texture: impl Into<crate::texture::TextureRef<'tex>>,
98 f: impl FnOnce() -> R,
99 ) -> R {
100 let _texture = self.push_texture_token(texture);
101 f()
102 }
103}