nsf_imgui/
imgui.rs

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