1use 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
18pub 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 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
134impl<'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 #[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}