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
10pub 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
80pub 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 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 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}