Skip to main content

dear_implot/plots/
image.rs

1//! Image plot implementation
2
3use super::{
4    Plot, PlotDataLayout, PlotError, PlotItemStyle, plot_spec_with_style, with_plot_str_or_empty,
5};
6use crate::{ImageFlags, ItemFlags, sys};
7use dear_imgui_rs::texture::TextureRef;
8use std::marker::PhantomData;
9
10fn to_sys_texture_ref<'tex>(texture: impl Into<TextureRef<'tex>>) -> sys::ImTextureRef_c {
11    let texture = texture.into().raw();
12    sys::ImTextureRef_c {
13        _TexData: texture._TexData as *mut sys::ImTextureData,
14        _TexID: texture._TexID as sys::ImTextureID,
15    }
16}
17
18/// Plot an image in plot coordinates using an ImGui texture reference.
19pub struct ImagePlot<'a, 'tex> {
20    label: &'a str,
21    tex_ref: sys::ImTextureRef_c,
22    _texture: PhantomData<&'tex mut dear_imgui_rs::texture::TextureData>,
23    bounds_min: sys::ImPlotPoint,
24    bounds_max: sys::ImPlotPoint,
25    uv0: [f32; 2],
26    uv1: [f32; 2],
27    tint: [f32; 4],
28    style: PlotItemStyle,
29    flags: ImageFlags,
30    item_flags: ItemFlags,
31}
32
33impl<'a, 'tex> super::PlotItemStyled for ImagePlot<'a, 'tex> {
34    fn style_mut(&mut self) -> &mut PlotItemStyle {
35        &mut self.style
36    }
37}
38
39impl<'a, 'tex> ImagePlot<'a, 'tex> {
40    pub fn new(
41        label: &'a str,
42        texture: impl Into<TextureRef<'tex>>,
43        bounds_min: sys::ImPlotPoint,
44        bounds_max: sys::ImPlotPoint,
45    ) -> Self {
46        Self {
47            label,
48            tex_ref: to_sys_texture_ref(texture),
49            _texture: PhantomData,
50            bounds_min,
51            bounds_max,
52            uv0: [0.0, 0.0],
53            uv1: [1.0, 1.0],
54            tint: [1.0, 1.0, 1.0, 1.0],
55            style: PlotItemStyle::default(),
56            flags: ImageFlags::NONE,
57            item_flags: ItemFlags::NONE,
58        }
59    }
60
61    pub fn with_uv(mut self, uv0: [f32; 2], uv1: [f32; 2]) -> Self {
62        self.uv0 = uv0;
63        self.uv1 = uv1;
64        self
65    }
66    pub fn with_tint(mut self, tint: [f32; 4]) -> Self {
67        self.tint = tint;
68        self
69    }
70    pub fn with_flags(mut self, flags: ImageFlags) -> Self {
71        self.flags = flags;
72        self
73    }
74
75    /// Set common item flags for this plot item (applies to all plot types)
76    pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
77        self.item_flags = flags;
78        self
79    }
80
81    pub fn validate(&self) -> Result<(), PlotError> {
82        Ok(())
83    }
84}
85
86impl<'a, 'tex> Plot for ImagePlot<'a, 'tex> {
87    fn plot(&self, plot_ui: &crate::PlotUi<'_>) {
88        if self.validate().is_err() {
89            return;
90        }
91        let uv0 = sys::ImVec2_c {
92            x: self.uv0[0],
93            y: self.uv0[1],
94        };
95        let uv1 = sys::ImVec2_c {
96            x: self.uv1[0],
97            y: self.uv1[1],
98        };
99        let tint = sys::ImVec4_c {
100            x: self.tint[0],
101            y: self.tint[1],
102            z: self.tint[2],
103            w: self.tint[3],
104        };
105        let tex_ref = sys::ImTextureRef_c {
106            _TexData: self.tex_ref._TexData,
107            _TexID: self.tex_ref._TexID,
108        };
109        let _guard = plot_ui.bind();
110        with_plot_str_or_empty(self.label, |label_ptr| unsafe {
111            let spec = plot_spec_with_style(
112                self.style,
113                self.flags.bits() | self.item_flags.bits(),
114                PlotDataLayout::DEFAULT,
115            );
116            sys::ImPlot_PlotImage(
117                label_ptr,
118                tex_ref,
119                self.bounds_min,
120                self.bounds_max,
121                uv0,
122                uv1,
123                tint,
124                spec,
125            )
126        })
127    }
128
129    fn label(&self) -> &str {
130        self.label
131    }
132}
133
134/// Convenience methods on PlotUi
135impl<'ui> crate::PlotUi<'ui> {
136    pub fn plot_image<'tex>(
137        &self,
138        label: &str,
139        texture: impl Into<TextureRef<'tex>>,
140        bounds_min: sys::ImPlotPoint,
141        bounds_max: sys::ImPlotPoint,
142    ) -> Result<(), PlotError> {
143        let plot = ImagePlot::new(label, texture, bounds_min, bounds_max);
144        plot.validate()?;
145        plot.plot(self);
146        Ok(())
147    }
148
149    /// Plot an image using ImGui's TextureId wrapper (if available)
150    #[allow(unused_variables)]
151    pub fn plot_image_with_imgui_texture(
152        &self,
153        label: &str,
154        texture: dear_imgui_rs::TextureId,
155        bounds_min: sys::ImPlotPoint,
156        bounds_max: sys::ImPlotPoint,
157    ) -> Result<(), PlotError> {
158        self.plot_image(label, texture, bounds_min, bounds_max)
159    }
160}