1use crate::flags::Marker3D;
2use crate::sys;
3use std::borrow::Cow;
4
5#[repr(i32)]
7#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8pub enum Plot3DColorElement {
9 TitleText = sys::ImPlot3DCol_TitleText as i32,
10 InlayText = sys::ImPlot3DCol_InlayText as i32,
11 FrameBg = sys::ImPlot3DCol_FrameBg as i32,
12 PlotBg = sys::ImPlot3DCol_PlotBg as i32,
13 PlotBorder = sys::ImPlot3DCol_PlotBorder as i32,
14 LegendBg = sys::ImPlot3DCol_LegendBg as i32,
15 LegendBorder = sys::ImPlot3DCol_LegendBorder as i32,
16 LegendText = sys::ImPlot3DCol_LegendText as i32,
17 AxisText = sys::ImPlot3DCol_AxisText as i32,
18 AxisGrid = sys::ImPlot3DCol_AxisGrid as i32,
19 AxisTick = sys::ImPlot3DCol_AxisTick as i32,
20 AxisBg = sys::ImPlot3DCol_AxisBg as i32,
21 AxisBgHovered = sys::ImPlot3DCol_AxisBgHovered as i32,
22 AxisBgActive = sys::ImPlot3DCol_AxisBgActive as i32,
23}
24
25#[inline]
26pub fn style_colors_dark() {
27 unsafe { sys::ImPlot3D_StyleColorsDark(std::ptr::null_mut()) }
28}
29#[inline]
30pub fn style_colors_light() {
31 unsafe { sys::ImPlot3D_StyleColorsLight(std::ptr::null_mut()) }
32}
33#[inline]
34pub fn style_colors_classic() {
35 unsafe { sys::ImPlot3D_StyleColorsClassic(std::ptr::null_mut()) }
36}
37#[inline]
38pub fn style_colors_auto() {
39 unsafe { sys::ImPlot3D_StyleColorsAuto(std::ptr::null_mut()) }
40}
41
42#[inline]
43pub fn push_style_color(idx: i32, col: [f32; 4]) {
44 unsafe {
45 sys::ImPlot3D_PushStyleColor_Vec4(idx, crate::imvec4(col[0], col[1], col[2], col[3]));
46 }
47}
48
49#[inline]
51pub fn push_style_color_element(element: Plot3DColorElement, col: [f32; 4]) {
52 push_style_color(element as i32, col);
53}
54
55#[inline]
56pub fn pop_style_color(count: i32) {
57 unsafe { sys::ImPlot3D_PopStyleColor(count) }
58}
59
60#[inline]
62pub fn push_style_var_f32(idx: i32, val: f32) {
63 unsafe { sys::ImPlot3D_PushStyleVar_Float(idx, val) }
64}
65
66#[inline]
68pub fn push_style_var_i32(idx: i32, val: i32) {
69 unsafe { sys::ImPlot3D_PushStyleVar_Int(idx, val) }
70}
71
72#[inline]
74pub fn push_style_var_vec2(idx: i32, val: [f32; 2]) {
75 unsafe { sys::ImPlot3D_PushStyleVar_Vec2(idx, crate::imvec2(val[0], val[1])) }
76}
77
78#[inline]
80pub fn pop_style_var(count: i32) {
81 unsafe { sys::ImPlot3D_PopStyleVar(count) }
82}
83
84#[inline]
85pub fn set_next_line_style(col: [f32; 4], weight: f32) {
86 crate::update_next_plot3d_spec(|spec| {
87 spec.LineColor = crate::imvec4(col[0], col[1], col[2], col[3]);
88 spec.LineWeight = weight;
89 })
90}
91
92#[inline]
93pub fn set_next_fill_style(col: [f32; 4], alpha_mod: f32) {
94 crate::update_next_plot3d_spec(|spec| {
95 spec.FillColor = crate::imvec4(col[0], col[1], col[2], col[3]);
96 spec.FillAlpha = alpha_mod;
97 })
98}
99
100#[inline]
101pub fn set_next_marker_style(
102 marker: Marker3D,
103 size: f32,
104 fill: [f32; 4],
105 weight: f32,
106 outline: [f32; 4],
107) {
108 crate::update_next_plot3d_spec(|spec| {
109 spec.Marker = marker as sys::ImPlot3DMarker;
110 spec.MarkerSize = size;
111 spec.MarkerFillColor = crate::imvec4(fill[0], fill[1], fill[2], fill[3]);
112 spec.MarkerLineColor = crate::imvec4(outline[0], outline[1], outline[2], outline[3]);
113 spec.LineWeight = weight;
114 })
115}
116
117#[derive(Debug, Clone, Default, PartialEq)]
119pub struct Plot3DItemArrayStyle<'a> {
120 line_colors: Option<Cow<'a, [u32]>>,
121 fill_colors: Option<Cow<'a, [u32]>>,
122 marker_sizes: Option<Cow<'a, [f32]>>,
123 marker_line_colors: Option<Cow<'a, [u32]>>,
124 marker_fill_colors: Option<Cow<'a, [u32]>>,
125}
126
127impl<'a> Plot3DItemArrayStyle<'a> {
128 pub fn new() -> Self {
130 Self::default()
131 }
132
133 pub fn with_line_colors(mut self, colors: &'a [u32]) -> Self {
135 self.line_colors = Some(Cow::Borrowed(colors));
136 self
137 }
138
139 pub fn with_fill_colors(mut self, colors: &'a [u32]) -> Self {
141 self.fill_colors = Some(Cow::Borrowed(colors));
142 self
143 }
144
145 pub fn with_marker_sizes(mut self, sizes: &'a [f32]) -> Self {
147 self.marker_sizes = Some(Cow::Borrowed(sizes));
148 self
149 }
150
151 pub fn with_marker_line_colors(mut self, colors: &'a [u32]) -> Self {
153 self.marker_line_colors = Some(Cow::Borrowed(colors));
154 self
155 }
156
157 pub fn with_marker_fill_colors(mut self, colors: &'a [u32]) -> Self {
159 self.marker_fill_colors = Some(Cow::Borrowed(colors));
160 self
161 }
162
163 fn apply_to_spec(&self, spec: &mut sys::ImPlot3DSpec_c) {
164 spec.LineColors = self
165 .line_colors
166 .as_ref()
167 .map_or(std::ptr::null_mut(), |colors| colors.as_ptr() as *mut _);
168 spec.FillColors = self
169 .fill_colors
170 .as_ref()
171 .map_or(std::ptr::null_mut(), |colors| colors.as_ptr() as *mut _);
172 spec.MarkerSizes = self
173 .marker_sizes
174 .as_ref()
175 .map_or(std::ptr::null_mut(), |sizes| sizes.as_ptr() as *mut _);
176 spec.MarkerLineColors = self
177 .marker_line_colors
178 .as_ref()
179 .map_or(std::ptr::null_mut(), |colors| colors.as_ptr() as *mut _);
180 spec.MarkerFillColors = self
181 .marker_fill_colors
182 .as_ref()
183 .map_or(std::ptr::null_mut(), |colors| colors.as_ptr() as *mut _);
184 }
185}
186
187pub fn with_next_plot3d_item_array_style<'a, R>(
189 style: Plot3DItemArrayStyle<'a>,
190 f: impl FnOnce() -> R,
191) -> R {
192 let previous = crate::take_next_plot3d_spec();
193 let mut spec = previous.unwrap_or_else(crate::default_plot3d_spec);
194 style.apply_to_spec(&mut spec);
195 crate::set_next_plot3d_spec(Some(spec));
196
197 let out = f();
198
199 if crate::take_next_plot3d_spec().is_some() {
200 crate::set_next_plot3d_spec(previous);
201 }
202
203 out
204}
205
206#[inline]
207pub fn push_colormap_index(cmap_index: i32) {
208 unsafe { sys::ImPlot3D_PushColormap_Plot3DColormap(cmap_index) }
209}
210#[inline]
211pub fn push_colormap_name(name: &str) {
212 dear_imgui_rs::with_scratch_txt(name, |ptr| unsafe { sys::ImPlot3D_PushColormap_Str(ptr) })
213}
214#[inline]
215pub fn pop_colormap(count: i32) {
216 unsafe { sys::ImPlot3D_PopColormap(count) }
217}
218#[inline]
219pub fn colormap_count() -> i32 {
220 unsafe { sys::ImPlot3D_GetColormapCount() }
221}
222#[inline]
223pub fn colormap_name(index: i32) -> String {
224 unsafe {
225 let p = sys::ImPlot3D_GetColormapName(index);
226 if p.is_null() {
227 return String::new();
228 }
229 std::ffi::CStr::from_ptr(p).to_string_lossy().into_owned()
230 }
231}
232
233#[inline]
235pub fn colormap_size(index: i32) -> i32 {
236 unsafe { sys::ImPlot3D_GetColormapSize(index) }
237}
238
239#[inline]
241pub fn get_style_colormap_index() -> i32 {
242 unsafe {
243 let style = sys::ImPlot3D_GetStyle();
244 if style.is_null() {
245 return -1;
246 }
247 (*style).Colormap
248 }
249}
250
251#[inline]
253pub fn get_style_colormap_name() -> Option<String> {
254 let idx = get_style_colormap_index();
255 if idx < 0 {
256 return None;
257 }
258 let count = colormap_count();
259 if idx >= count {
260 return None;
261 }
262 Some(colormap_name(idx))
263}
264
265#[inline]
267pub fn set_style_colormap_index(index: i32) {
268 unsafe {
269 let style = sys::ImPlot3D_GetStyle();
270 if !style.is_null() {
271 let count = sys::ImPlot3D_GetColormapCount();
272 if count > 0 {
273 let idx = if index < 0 {
274 0
275 } else if index >= count {
276 count - 1
277 } else {
278 index
279 };
280 (*style).Colormap = idx;
281 }
282 }
283 }
284}
285
286#[inline]
288pub fn colormap_index_by_name(name: &str) -> i32 {
289 if name.contains('\0') {
290 return -1;
291 }
292 dear_imgui_rs::with_scratch_txt(name, |ptr| unsafe { sys::ImPlot3D_GetColormapIndex(ptr) })
293}
294
295#[inline]
297pub fn set_style_colormap_by_name(name: &str) {
298 let idx = colormap_index_by_name(name);
299 if idx >= 0 {
300 set_style_colormap_index(idx);
301 }
302}
303
304pub fn get_colormap_color(idx: i32) -> [f32; 4] {
306 unsafe {
307 let out = crate::compat_ffi::ImPlot3D_GetColormapColor(idx, (-1) as sys::ImPlot3DColormap);
309 [out.x, out.y, out.z, out.w]
310 }
311}
312
313pub fn next_colormap_color() -> [f32; 4] {
315 unsafe {
316 let out = crate::compat_ffi::ImPlot3D_NextColormapColor();
317 [out.x, out.y, out.z, out.w]
318 }
319}
320
321#[cfg(test)]
322mod tests {
323 use super::{Plot3DItemArrayStyle, with_next_plot3d_item_array_style};
324
325 #[test]
326 fn next_plot3d_item_array_style_is_consumed_by_next_spec() {
327 let line_colors = [0x01020304u32, 0x05060708];
328 let marker_sizes = [1.5f32, 2.5];
329 let marker_fill_colors = [0x11223344u32];
330
331 with_next_plot3d_item_array_style(
332 Plot3DItemArrayStyle::new()
333 .with_line_colors(&line_colors)
334 .with_marker_sizes(&marker_sizes)
335 .with_marker_fill_colors(&marker_fill_colors),
336 || {
337 let spec = crate::plot3d_spec_from(9, 2, 24);
338 assert_eq!(spec.Flags, 9);
339 assert_eq!(spec.Offset, 2);
340 assert_eq!(spec.Stride, 24);
341 assert_eq!(spec.LineColors, line_colors.as_ptr() as *mut _);
342 assert_eq!(spec.MarkerSizes, marker_sizes.as_ptr() as *mut _);
343 assert_eq!(spec.MarkerFillColors, marker_fill_colors.as_ptr() as *mut _);
344 },
345 );
346
347 let spec = crate::plot3d_spec_from(0, 0, -1);
348 assert!(spec.LineColors.is_null());
349 assert!(spec.MarkerSizes.is_null());
350 assert!(spec.MarkerFillColors.is_null());
351 }
352
353 #[test]
354 fn next_plot3d_item_array_style_is_restored_if_unused() {
355 let fill_colors = [0xAABBCCDDu32];
356
357 with_next_plot3d_item_array_style(
358 Plot3DItemArrayStyle::new().with_fill_colors(&fill_colors),
359 || {},
360 );
361
362 let spec = crate::plot3d_spec_from(0, 0, -1);
363 assert!(spec.FillColors.is_null());
364 }
365}