use std::{
cell::UnsafeCell,
ops::{Deref, DerefMut},
ptr::{null, null_mut},
sync::OnceLock,
};
use imgui::{Context, Ui, UiBuffer};
use imgui_sys::{
igGetCurrentContext, igGetIO, igStyleColorsDark, igStyleColorsLight,
ImFontAtlas_AddFontDefault, ImGuiStyle,
};
use super::drawing::RaylibDrawHandle;
static mut CONTEXT: OnceLock<Context> = OnceLock::new();
fn context() -> &'static Context {
unsafe { CONTEXT.get_or_init(|| imgui::Context::create()) }
}
pub(crate) unsafe fn init_imgui_context(dark: bool) {
context();
if dark {
igStyleColorsDark(null_mut() as *mut ImGuiStyle);
} else {
igStyleColorsLight(null_mut() as *mut ImGuiStyle);
}
let io = igGetIO().as_ref().unwrap();
ImFontAtlas_AddFontDefault(io.Fonts, null());
raylib_sys::rlImGuiEndInitImGui();
}
pub struct RayImGUIHandle(Ui);
impl RayImGUIHandle {
fn new() -> Option<Self> {
unsafe {
if let Some(_ctx) = igGetCurrentContext().as_mut() {
if let Some(io) = igGetIO().as_mut() {
if io.DeltaTime <= 0.0 {
io.DeltaTime = 0.01;
return None;
}
}
}
raylib_sys::rlImGuiBegin();
};
Some(Self(unsafe {
std::mem::transmute(UnsafeCell::new(UiBuffer::new(1024)))
}))
}
}
impl Drop for RayImGUIHandle {
fn drop(&mut self) {
unsafe {
raylib_sys::rlImGuiEnd();
}
}
}
impl Deref for RayImGUIHandle {
type Target = Ui;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for RayImGUIHandle {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub trait RayImGUITrait {
fn begin_imgui(&self) -> Option<RayImGUIHandle> {
return RayImGUIHandle::new();
}
fn draw_imgui(&self, f: impl Fn(&mut Ui)) {
if let Some(mut new_frame) = RayImGUIHandle::new() {
f(&mut new_frame);
}
}
}
impl RayImGUITrait for RaylibDrawHandle<'_> {}
#[cfg(feature = "imgui")]
#[derive(Debug, PartialEq)]
pub enum ImGuiTheme {
Light,
Dark,
}
#[cfg(feature = "imgui")]
impl Default for ImGuiTheme {
fn default() -> Self {
Self::Dark
}
}