dear-implot3d 0.17.0

High-level Rust bindings to ImPlot3D with dear-imgui-rs integration
Documentation
use crate::sys;
use dear_imgui_rs::{ContextBinding, ContextBindingError};

#[derive(Clone)]
pub(crate) struct Plot3DContextBinding {
    pub(crate) plot_ctx_raw: *mut sys::ImPlot3DContext,
    pub(crate) imgui_binding: ContextBinding,
}

#[must_use = "dropping the guard restores the previous ImPlot3D context"]
struct Plot3DContextGuard {
    prev_plot_ctx_raw: *mut sys::ImPlot3DContext,
    restore_plot: bool,
}

impl Plot3DContextBinding {
    pub(crate) fn with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
        self.imgui_binding.with_bound_context(|| {
            let _guard = Plot3DContextGuard::bind(self.plot_ctx_raw);
            f()
        })
    }

    pub(crate) fn try_with_bound_context<R>(
        &self,
        f: impl FnOnce() -> R,
    ) -> Result<R, ContextBindingError> {
        self.imgui_binding.try_with_bound_context(|| {
            let _guard = Plot3DContextGuard::bind(self.plot_ctx_raw);
            f()
        })
    }
}

impl Plot3DContextGuard {
    fn bind(plot_ctx_raw: *mut sys::ImPlot3DContext) -> Self {
        assert!(
            !plot_ctx_raw.is_null(),
            "dear-implot3d: Plot3DUi requires an active ImPlot3D context"
        );
        let prev_plot_ctx_raw = unsafe { sys::ImPlot3D_GetCurrentContext() };
        let restore_plot = prev_plot_ctx_raw != plot_ctx_raw;
        unsafe {
            sys::ImPlot3D_SetCurrentContext(plot_ctx_raw);
        }
        Self {
            prev_plot_ctx_raw,
            restore_plot,
        }
    }
}

impl Drop for Plot3DContextGuard {
    fn drop(&mut self) {
        if self.restore_plot {
            unsafe {
                sys::ImPlot3D_SetCurrentContext(self.prev_plot_ctx_raw);
            }
        }
    }
}