Skip to main content

dear_implot3d/
builder.rs

1use std::marker::PhantomData;
2
3use crate::ui::{Plot3DContextBinding, Plot3DToken};
4use crate::{Plot3DFlags, debug_begin_plot, imvec2, sys};
5use dear_imgui_rs::Ui;
6
7/// Plot builder for configuring the 3D plot
8pub struct Plot3DBuilder<'ui> {
9    pub(crate) binding: Plot3DContextBinding,
10    pub(crate) imgui_alive: Option<dear_imgui_rs::ContextAliveToken>,
11    pub(crate) ui: &'ui Ui,
12    pub(crate) title: String,
13    pub(crate) size: Option<[f32; 2]>,
14    pub(crate) flags: Plot3DFlags,
15    pub(crate) _lifetime: PhantomData<&'ui Ui>,
16}
17
18impl<'ui> Plot3DBuilder<'ui> {
19    pub fn size(mut self, size: [f32; 2]) -> Self {
20        self.size = Some(size);
21        self
22    }
23    pub fn flags(mut self, flags: Plot3DFlags) -> Self {
24        self.flags = flags;
25        self
26    }
27    pub fn build(self) -> Option<Plot3DToken<'ui>> {
28        if let Some(alive) = &self.imgui_alive {
29            assert!(
30                alive.is_alive(),
31                "dear-implot3d: ImGui context has been dropped"
32            );
33        }
34        let _guard = self.binding.bind();
35        if self.title.contains('\0') {
36            return None;
37        }
38        let title = self.title;
39        let size = self.size.unwrap_or([0.0, 0.0]);
40        let ok = dear_imgui_rs::with_scratch_txt(&title, |title_ptr| unsafe {
41            // Defensive: ensure style.Colormap is in range before plotting
42            let style = sys::ImPlot3D_GetStyle();
43            if !style.is_null() {
44                let count = sys::ImPlot3D_GetColormapCount();
45                if count > 0 && ((*style).Colormap < 0 || (*style).Colormap >= count) {
46                    (*style).Colormap = 0;
47                }
48            }
49            sys::ImPlot3D_BeginPlot(
50                title_ptr,
51                imvec2(size[0], size[1]),
52                self.flags.bits() as i32,
53            )
54        });
55        if ok {
56            debug_begin_plot();
57            Some(Plot3DToken {
58                binding: self.binding,
59                imgui_alive: self.imgui_alive.clone(),
60                ui: self.ui,
61                _lifetime: PhantomData,
62            })
63        } else {
64            None
65        }
66    }
67}