1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
mod auto; pub use crate::auto::types_used::*; pub use crate::auto::*; use lazy_static::lazy_static; use nsf_imgui_raw::*; use std::ffi::CStr; use std::os::raw::{c_char, c_int, c_void}; use std::rc::Rc; use std::sync::Mutex; lazy_static! { static ref IMGUI_INSTANCE_ALIVE: Mutex<bool> = Mutex::new(false); } pub struct ImGuiOwner; impl Drop for ImGuiOwner { fn drop(&mut self) { let mut is_alive = IMGUI_INSTANCE_ALIVE.lock().unwrap(); unsafe { igDestroyContext(igGetCurrentContext()); } *is_alive = false; } } #[derive(Clone)] pub struct ImGui { imgui_owner: Rc<ImGuiOwner>, } impl ImGui { pub fn new() -> Result<ImGui, String> { let mut is_alive = IMGUI_INSTANCE_ALIVE.lock().unwrap(); if *is_alive { Err("Cannot initialize `ImGui` more than once at a time.".to_owned()) } else { unsafe { igCreateContext(std::ptr::null_mut()) }; *is_alive = true; Ok(ImGui { imgui_owner: Rc::new(ImGuiOwner), }) } } extern "C" fn input_text_callback(data: *mut ImGuiInputTextCallbackData) -> c_int { unsafe { let s = (*data).user_data as *mut String; if (*data).event_flag == ImGuiInputTextFlags::CallbackResize { while (*s).len() < (*data).buf_size as usize { (*s).push('\0'); } if (*s).len() > (*data).buf_size as usize { (*s).truncate((*data).buf_size as usize); } (*data).buf = (*s).as_ptr() as *mut c_char; } } 0 } #[inline] pub fn input_text(&self, label: &CStr, s: &mut String, extra_flags: impl Into<Option<ImGuiInputTextFlags>>) { s.push('\0'); unsafe { igInputText( label.as_ptr(), s.as_ptr() as *mut c_char, s.len(), match extra_flags.into() { Some(v) => v | ImGuiInputTextFlags::CallbackResize, None => ImGuiInputTextFlags::CallbackResize, }, Some(Self::input_text_callback), s as *mut String as *mut c_void, ); } s.pop(); } } #[macro_export] macro_rules! cstr_ptr { ($s:expr) => { concat!($s, "\0") as *const str as *const [::std::os::raw::c_char] as *const ::std::os::raw::c_char }; } #[macro_export] macro_rules! cstr { ($s:expr) => ( unsafe { ::std::ffi::CStr::from_ptr(cstr_ptr!($s)) } ); ($s:expr, $($arg:expr),*) => ( unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(&format!(concat!($s, "\0"), $($arg),*).into_bytes()) } ); }