dear_implot/plots/
image.rs

1//! Image plot implementation
2
3use super::{Plot, PlotError, safe_cstring};
4use crate::{ImageFlags, sys};
5
6/// Plot an image in plot coordinates using an ImTextureID
7pub struct ImagePlot<'a> {
8    label: &'a str,
9    tex_id: sys::ImTextureID,
10    bounds_min: sys::ImPlotPoint,
11    bounds_max: sys::ImPlotPoint,
12    uv0: [f32; 2],
13    uv1: [f32; 2],
14    tint: [f32; 4],
15    flags: ImageFlags,
16}
17
18impl<'a> ImagePlot<'a> {
19    pub fn new(
20        label: &'a str,
21        tex_id: sys::ImTextureID,
22        bounds_min: sys::ImPlotPoint,
23        bounds_max: sys::ImPlotPoint,
24    ) -> Self {
25        Self {
26            label,
27            tex_id,
28            bounds_min,
29            bounds_max,
30            uv0: [0.0, 0.0],
31            uv1: [1.0, 1.0],
32            tint: [1.0, 1.0, 1.0, 1.0],
33            flags: ImageFlags::NONE,
34        }
35    }
36
37    pub fn with_uv(mut self, uv0: [f32; 2], uv1: [f32; 2]) -> Self {
38        self.uv0 = uv0;
39        self.uv1 = uv1;
40        self
41    }
42    pub fn with_tint(mut self, tint: [f32; 4]) -> Self {
43        self.tint = tint;
44        self
45    }
46    pub fn with_flags(mut self, flags: ImageFlags) -> Self {
47        self.flags = flags;
48        self
49    }
50
51    pub fn validate(&self) -> Result<(), PlotError> {
52        Ok(())
53    }
54}
55
56impl<'a> Plot for ImagePlot<'a> {
57    fn plot(&self) {
58        if self.validate().is_err() {
59            return;
60        }
61        let label_c = safe_cstring(self.label);
62        let uv0 = sys::ImVec2_c {
63            x: self.uv0[0],
64            y: self.uv0[1],
65        };
66        let uv1 = sys::ImVec2_c {
67            x: self.uv1[0],
68            y: self.uv1[1],
69        };
70        let tint = sys::ImVec4_c {
71            x: self.tint[0],
72            y: self.tint[1],
73            z: self.tint[2],
74            w: self.tint[3],
75        };
76        // Construct ImTextureRef from ImTextureID
77        let tex_ref = sys::ImTextureRef_c {
78            _TexData: std::ptr::null_mut(),
79            _TexID: self.tex_id,
80        };
81        unsafe {
82            sys::ImPlot_PlotImage(
83                label_c.as_ptr(),
84                tex_ref,
85                self.bounds_min,
86                self.bounds_max,
87                uv0,
88                uv1,
89                tint,
90                self.flags.bits() as i32,
91            )
92        }
93    }
94
95    fn label(&self) -> &str {
96        self.label
97    }
98}
99
100/// Convenience methods on PlotUi
101impl<'ui> crate::PlotUi<'ui> {
102    pub fn plot_image(
103        &self,
104        label: &str,
105        tex_id: sys::ImTextureID,
106        bounds_min: sys::ImPlotPoint,
107        bounds_max: sys::ImPlotPoint,
108    ) -> Result<(), PlotError> {
109        let plot = ImagePlot::new(label, tex_id, bounds_min, bounds_max);
110        plot.validate()?;
111        plot.plot();
112        Ok(())
113    }
114
115    /// Plot an image using ImGui's TextureId wrapper (if available)
116    #[allow(unused_variables)]
117    pub fn plot_image_with_imgui_texture(
118        &self,
119        label: &str,
120        texture: dear_imgui_rs::TextureId,
121        bounds_min: sys::ImPlotPoint,
122        bounds_max: sys::ImPlotPoint,
123    ) -> Result<(), PlotError> {
124        // dear_imgui_rs::TextureId is a transparent wrapper; cast to sys::ImTextureID via `id()` then transmute
125        // This is a common interop pattern across imgui backends.
126        let raw: sys::ImTextureID = unsafe { std::mem::transmute(texture.id()) };
127        self.plot_image(label, raw, bounds_min, bounds_max)
128    }
129}