Skip to main content

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}