Skip to main content

dear_implot3d/
image_builder.rs

1use std::borrow::Cow;
2
3use dear_imgui_rs::texture::TextureRef;
4
5use crate::item_style::{Plot3DItemStyle, plot3d_spec_with_style};
6use crate::{
7    Image3DFlags, Item3DFlags, Plot3DDataLayout, Plot3DUi, debug_before_plot, imvec2, imvec4, sys,
8};
9
10/// Image by axes builder
11pub struct Image3DByAxesBuilder<'ui, 'tex> {
12    pub(crate) _ui: &'ui Plot3DUi<'ui>,
13    pub(crate) label: Cow<'ui, str>,
14    pub(crate) texture: TextureRef<'tex>,
15    pub(crate) center: [f32; 3],
16    pub(crate) axis_u: [f32; 3],
17    pub(crate) axis_v: [f32; 3],
18    pub(crate) uv0: [f32; 2],
19    pub(crate) uv1: [f32; 2],
20    pub(crate) tint: [f32; 4],
21    pub(crate) flags: Image3DFlags,
22    pub(crate) item_flags: Item3DFlags,
23    pub(crate) style: Plot3DItemStyle,
24}
25
26impl<'ui, 'tex> Image3DByAxesBuilder<'ui, 'tex> {
27    pub fn uv(mut self, uv0: [f32; 2], uv1: [f32; 2]) -> Self {
28        self.uv0 = uv0;
29        self.uv1 = uv1;
30        self
31    }
32    pub fn tint(mut self, col: [f32; 4]) -> Self {
33        self.tint = col;
34        self
35    }
36    pub fn flags(mut self, flags: Image3DFlags) -> Self {
37        self.flags = flags;
38        self
39    }
40    pub fn plot(self) {
41        self._ui.with_bound_context(|| {
42            let tex_ref = to_sys_texture_ref(self._ui, self.texture);
43            let label = self.label.as_ref();
44            let label = if label.contains('\0') { "image" } else { label };
45            dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
46                debug_before_plot();
47                let spec = plot3d_spec_with_style(
48                    self.style,
49                    self.flags.bits() | self.item_flags.bits(),
50                    Plot3DDataLayout::DEFAULT,
51                );
52                sys::ImPlot3D_PlotImage_Vec2(
53                    label_ptr,
54                    tex_ref,
55                    sys::ImPlot3DPoint_c {
56                        x: self.center[0] as f64,
57                        y: self.center[1] as f64,
58                        z: self.center[2] as f64,
59                    },
60                    sys::ImPlot3DPoint_c {
61                        x: self.axis_u[0] as f64,
62                        y: self.axis_u[1] as f64,
63                        z: self.axis_u[2] as f64,
64                    },
65                    sys::ImPlot3DPoint_c {
66                        x: self.axis_v[0] as f64,
67                        y: self.axis_v[1] as f64,
68                        z: self.axis_v[2] as f64,
69                    },
70                    imvec2(self.uv0[0], self.uv0[1]),
71                    imvec2(self.uv1[0], self.uv1[1]),
72                    imvec4(self.tint[0], self.tint[1], self.tint[2], self.tint[3]),
73                    spec,
74                );
75            })
76        })
77    }
78}
79
80/// Image by corners builder
81pub struct Image3DByCornersBuilder<'ui, 'tex> {
82    pub(crate) _ui: &'ui Plot3DUi<'ui>,
83    pub(crate) label: Cow<'ui, str>,
84    pub(crate) texture: TextureRef<'tex>,
85    pub(crate) p0: [f32; 3],
86    pub(crate) p1: [f32; 3],
87    pub(crate) p2: [f32; 3],
88    pub(crate) p3: [f32; 3],
89    pub(crate) uv0: [f32; 2],
90    pub(crate) uv1: [f32; 2],
91    pub(crate) uv2: [f32; 2],
92    pub(crate) uv3: [f32; 2],
93    pub(crate) tint: [f32; 4],
94    pub(crate) flags: Image3DFlags,
95    pub(crate) item_flags: Item3DFlags,
96    pub(crate) style: Plot3DItemStyle,
97}
98
99impl<'ui, 'tex> Image3DByCornersBuilder<'ui, 'tex> {
100    pub fn uvs(mut self, uv0: [f32; 2], uv1: [f32; 2], uv2: [f32; 2], uv3: [f32; 2]) -> Self {
101        self.uv0 = uv0;
102        self.uv1 = uv1;
103        self.uv2 = uv2;
104        self.uv3 = uv3;
105        self
106    }
107    pub fn tint(mut self, col: [f32; 4]) -> Self {
108        self.tint = col;
109        self
110    }
111    pub fn flags(mut self, flags: Image3DFlags) -> Self {
112        self.flags = flags;
113        self
114    }
115    pub fn plot(self) {
116        self._ui.with_bound_context(|| {
117            let tex_ref = to_sys_texture_ref(self._ui, self.texture);
118            let label = self.label.as_ref();
119            let label = if label.contains('\0') { "image" } else { label };
120            dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
121                debug_before_plot();
122                let spec = plot3d_spec_with_style(
123                    self.style,
124                    self.flags.bits() | self.item_flags.bits(),
125                    Plot3DDataLayout::DEFAULT,
126                );
127                sys::ImPlot3D_PlotImage_Plot3DPoint(
128                    label_ptr,
129                    tex_ref,
130                    sys::ImPlot3DPoint_c {
131                        x: self.p0[0] as f64,
132                        y: self.p0[1] as f64,
133                        z: self.p0[2] as f64,
134                    },
135                    sys::ImPlot3DPoint_c {
136                        x: self.p1[0] as f64,
137                        y: self.p1[1] as f64,
138                        z: self.p1[2] as f64,
139                    },
140                    sys::ImPlot3DPoint_c {
141                        x: self.p2[0] as f64,
142                        y: self.p2[1] as f64,
143                        z: self.p2[2] as f64,
144                    },
145                    sys::ImPlot3DPoint_c {
146                        x: self.p3[0] as f64,
147                        y: self.p3[1] as f64,
148                        z: self.p3[2] as f64,
149                    },
150                    imvec2(self.uv0[0], self.uv0[1]),
151                    imvec2(self.uv1[0], self.uv1[1]),
152                    imvec2(self.uv2[0], self.uv2[1]),
153                    imvec2(self.uv3[0], self.uv3[1]),
154                    imvec4(self.tint[0], self.tint[1], self.tint[2], self.tint[3]),
155                    spec,
156                );
157            })
158        })
159    }
160}
161
162impl<'ui> Plot3DUi<'ui> {
163    /// Image oriented by center and axes
164    pub fn image_by_axes<'tex, T: Into<TextureRef<'tex>>>(
165        &'ui self,
166        label: impl Into<Cow<'ui, str>>,
167        tex: T,
168        center: [f32; 3],
169        axis_u: [f32; 3],
170        axis_v: [f32; 3],
171    ) -> Image3DByAxesBuilder<'ui, 'tex> {
172        Image3DByAxesBuilder {
173            _ui: self,
174            label: label.into(),
175            texture: tex.into(),
176            center,
177            axis_u,
178            axis_v,
179            uv0: [0.0, 0.0],
180            uv1: [1.0, 1.0],
181            tint: [1.0, 1.0, 1.0, 1.0],
182            flags: Image3DFlags::NONE,
183            item_flags: Item3DFlags::NONE,
184            style: Plot3DItemStyle::default(),
185        }
186    }
187
188    /// Image by 4 corner points (p0..p3)
189    pub fn image_by_corners<'tex, T: Into<TextureRef<'tex>>>(
190        &'ui self,
191        label: impl Into<Cow<'ui, str>>,
192        tex: T,
193        p0: [f32; 3],
194        p1: [f32; 3],
195        p2: [f32; 3],
196        p3: [f32; 3],
197    ) -> Image3DByCornersBuilder<'ui, 'tex> {
198        Image3DByCornersBuilder {
199            _ui: self,
200            label: label.into(),
201            texture: tex.into(),
202            p0,
203            p1,
204            p2,
205            p3,
206            uv0: [0.0, 0.0],
207            uv1: [1.0, 0.0],
208            uv2: [1.0, 1.0],
209            uv3: [0.0, 1.0],
210            tint: [1.0, 1.0, 1.0, 1.0],
211            flags: Image3DFlags::NONE,
212            item_flags: Item3DFlags::NONE,
213            style: Plot3DItemStyle::default(),
214        }
215    }
216}
217
218fn to_sys_texture_ref(ui: &Plot3DUi<'_>, texture: TextureRef<'_>) -> sys::ImTextureRef_c {
219    let texture = unsafe { ui._ui.resolve_texture_ref_raw(texture) }
220        .unwrap_or_else(|error| panic!("ImPlot3D image rejected texture: {error}"));
221    sys::ImTextureRef_c {
222        _TexData: texture._TexData as *mut sys::ImTextureData,
223        _TexID: texture._TexID as sys::ImTextureID,
224    }
225}