backup files removed

This commit is contained in:
orhanbalci 2016-05-28 14:41:11 +03:00
parent 6e184ad4d5
commit 9e6bf3948c
7 changed files with 0 additions and 863 deletions

View File

@ -1,209 +0,0 @@
use glium::{
index, program, texture, vertex,
Blend, DrawError, DrawParameters, GlObject, IndexBuffer, Program, Rect, Surface, Texture2d,
VertexBuffer
};
use glium::backend::{Context, Facade};
use glium::index::PrimitiveType;
use glium::texture::{ClientFormat, RawImage2d};
use libc::uintptr_t;
use std::borrow::Cow;
use std::fmt;
use std::rc::Rc;
use super::{DrawList, Ui, ImDrawIdx, ImDrawVert, ImGui};
pub type RendererResult<T> = Result<T, RendererError>;
#[derive(Clone, Debug)]
pub enum RendererError {
Vertex(vertex::BufferCreationError),
Index(index::BufferCreationError),
Program(program::ProgramChooserCreationError),
Texture(texture::TextureCreationError),
Draw(DrawError)
}
impl fmt::Display for RendererError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::RendererError::*;
match *self {
Vertex(_) => write!(f, "Vertex buffer creation failed"),
Index(_) => write!(f, "Index buffer creation failed"),
Program(ref e) => write!(f, "Program creation failed: {}", e),
Texture(_) => write!(f, "Texture creation failed"),
Draw(ref e) => write!(f, "Drawing failed: {}", e)
}
}
}
impl From<vertex::BufferCreationError> for RendererError {
fn from(e: vertex::BufferCreationError) -> RendererError {
RendererError::Vertex(e)
}
}
impl From<index::BufferCreationError> for RendererError {
fn from(e: index::BufferCreationError) -> RendererError {
RendererError::Index(e)
}
}
impl From<program::ProgramChooserCreationError> for RendererError {
fn from(e: program::ProgramChooserCreationError) -> RendererError {
RendererError::Program(e)
}
}
impl From<texture::TextureCreationError> for RendererError {
fn from(e: texture::TextureCreationError) -> RendererError {
RendererError::Texture(e)
}
}
impl From<DrawError> for RendererError {
fn from(e: DrawError) -> RendererError {
RendererError::Draw(e)
}
}
pub struct Renderer {
ctx: Rc<Context>,
device_objects: DeviceObjects
}
impl Renderer {
pub fn init<F: Facade>(imgui: &mut ImGui, ctx: &F) -> RendererResult<Renderer> {
let device_objects = try!(DeviceObjects::init(imgui, ctx));
Ok(Renderer {
ctx: ctx.get_context().clone(),
device_objects: device_objects
})
}
pub fn render<'a, S: Surface>(&mut self, surface: &mut S,
ui: Ui<'a>) -> RendererResult<()> {
let _ = self.ctx.insert_debug_marker("imgui-rs: starting rendering");
let result = ui.render(|draw_list| self.render_draw_list(surface, draw_list));
let _ = self.ctx.insert_debug_marker("imgui-rs: rendering finished");
result
}
fn render_draw_list<'a, S: Surface>(&mut self, surface: &mut S,
draw_list: DrawList<'a>) -> RendererResult<()> {
try!(self.device_objects.upload_vertex_buffer(&self.ctx, draw_list.vtx_buffer));
try!(self.device_objects.upload_index_buffer(&self.ctx, draw_list.idx_buffer));
let (width, height) = surface.get_dimensions();
let matrix = [
[ 2.0 / (width as f32), 0.0, 0.0, 0.0 ],
[ 0.0, 2.0 / -(height as f32), 0.0, 0.0 ],
[ 0.0, 0.0, -1.0, 0.0 ],
[ -1.0, 1.0, 0.0, 1.0 ]
];
let font_texture_id = self.device_objects.texture.get_id() as uintptr_t;
let mut idx_start = 0;
for cmd in draw_list.cmd_buffer {
// We don't support custom textures...yet!
assert!(cmd.texture_id as uintptr_t == font_texture_id);
let uniforms = uniform! {
matrix: matrix,
tex: &self.device_objects.texture
};
let draw_params = DrawParameters {
blend: Blend::alpha_blending(),
scissor: Some(Rect {
left: cmd.clip_rect.x as u32,
bottom: (height as f32 - cmd.clip_rect.w) as u32,
width: (cmd.clip_rect.z - cmd.clip_rect.x) as u32,
height: (cmd.clip_rect.w - cmd.clip_rect.y) as u32
}),
.. Default::default()
};
let idx_end = idx_start + cmd.elem_count as usize;
try!(surface.draw(&self.device_objects.vertex_buffer,
&self.device_objects.index_buffer.slice(idx_start ..idx_end)
.expect("Invalid index buffer range"),
&self.device_objects.program,
&uniforms,
&draw_params));
idx_start = idx_end;
}
Ok(())
}
}
pub struct DeviceObjects {
vertex_buffer: VertexBuffer<ImDrawVert>,
index_buffer: IndexBuffer<ImDrawIdx>,
program: Program,
texture: Texture2d
}
fn compile_default_program<F: Facade>(ctx: &F) -> Result<Program, program::ProgramChooserCreationError> {
program!(
ctx,
140 => {
vertex: include_str!("shader/vert_140.glsl"),
fragment: include_str!("shader/frag_140.glsl"),
outputs_srgb: true
},
110 => {
vertex: include_str!("shader/vert_110.glsl"),
fragment: include_str!("shader/frag_110.glsl"),
outputs_srgb: true
}
)
}
impl DeviceObjects {
pub fn init<F: Facade>(im_gui: &mut ImGui, ctx: &F) -> RendererResult<DeviceObjects> {
let vertex_buffer = try!(VertexBuffer::empty_dynamic(ctx, 0));
let index_buffer = try!(IndexBuffer::empty_dynamic(ctx, PrimitiveType::TrianglesList, 0));
let program = try!(compile_default_program(ctx));
let texture = try!(im_gui.prepare_texture(|handle| {
let data = RawImage2d {
data: Cow::Borrowed(handle.pixels),
width: handle.width,
height: handle.height,
format: ClientFormat::U8U8U8U8
};
Texture2d::new(ctx, data)
}));
im_gui.set_texture_id(texture.get_id() as uintptr_t);
Ok(DeviceObjects {
vertex_buffer: vertex_buffer,
index_buffer: index_buffer,
program: program,
texture: texture
})
}
pub fn upload_vertex_buffer<F: Facade>(&mut self, ctx: &F,
vtx_buffer: &[ImDrawVert]) -> RendererResult<()> {
self.vertex_buffer.invalidate();
if let Some(slice) = self.vertex_buffer.slice_mut(0 .. vtx_buffer.len()) {
slice.write(vtx_buffer);
return Ok(());
}
self.vertex_buffer = try!(VertexBuffer::dynamic(ctx, vtx_buffer));
let _ = ctx.get_context().insert_debug_marker(
&format!("imgui-rs: resized vertex buffer to {} bytes",
self.vertex_buffer.get_size()));
Ok(())
}
pub fn upload_index_buffer<F: Facade>(&mut self, ctx: &F,
idx_buffer: &[ImDrawIdx]) -> RendererResult<()> {
self.index_buffer.invalidate();
if let Some(slice) = self.index_buffer.slice_mut(0 .. idx_buffer.len()) {
slice.write(idx_buffer);
return Ok(());
}
self.index_buffer =
try!(IndexBuffer::dynamic(ctx, PrimitiveType::TrianglesList, idx_buffer));
let _ = ctx.get_context().insert_debug_marker(
&format!("imgui-rs: resized index buffer to {} bytes",
self.index_buffer.get_size()));
Ok(())
}
}

View File

@ -1,163 +0,0 @@
use imgui_sys;
use libc::size_t;
use std::marker::PhantomData;
use std::ptr;
use super::{
Ui,
ImGuiInputTextFlags, ImGuiInputTextFlags_CharsDecimal, ImGuiInputTextFlags_CharsHexadecimal,
ImGuiInputTextFlags_CharsUppercase, ImGuiInputTextFlags_CharsNoBlank,
ImGuiInputTextFlags_AutoSelectAll, ImGuiInputTextFlags_EnterReturnsTrue,
ImGuiInputTextFlags_CallbackCompletion, ImGuiInputTextFlags_CallbackHistory,
ImGuiInputTextFlags_CallbackAlways, ImGuiInputTextFlags_CallbackCharFilter,
ImGuiInputTextFlags_AllowTabInput, //ImGuiInputTextFlags_CtrlEnterForNewLine,
ImGuiInputTextFlags_NoHorizontalScroll, ImGuiInputTextFlags_AlwaysInsertMode,
ImStr
};
#[must_use]
pub struct InputText<'ui, 'p> {
label: ImStr<'p>,
buf: &'p mut str,
flags: ImGuiInputTextFlags,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> InputText<'ui, 'p> {
pub fn new(label: ImStr<'p>, buf: &'p mut str) -> Self {
InputText {
label: label,
buf: buf,
flags: ImGuiInputTextFlags::empty(),
_phantom: PhantomData
}
}
#[inline]
pub fn flags(self, flags: ImGuiInputTextFlags) -> Self {
InputText {
flags: flags,
.. self
}
}
#[inline]
pub fn chars_decimal(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CharsDecimal, value),
.. self
}
}
#[inline]
pub fn chars_hexadecimal(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CharsHexadecimal, value),
.. self
}
}
#[inline]
pub fn chars_uppercase(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CharsUppercase, value),
.. self
}
}
#[inline]
pub fn chars_noblank(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CharsNoBlank, value),
.. self
}
}
#[inline]
pub fn auto_select_all(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_AutoSelectAll, value),
.. self
}
}
#[inline]
pub fn enter_returns_true(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_EnterReturnsTrue, value),
.. self
}
}
#[inline]
pub fn callback_completion(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CallbackCompletion, value),
.. self
}
}
#[inline]
pub fn callback_history(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CallbackHistory, value),
.. self
}
}
#[inline]
pub fn callback_always(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CallbackAlways, value),
.. self
}
}
#[inline]
pub fn callback_char_filter(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_CallbackCharFilter, value),
.. self
}
}
#[inline]
pub fn allow_tab_input(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_AllowTabInput, value),
.. self
}
}
#[inline]
pub fn no_horizontal_scroll(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_NoHorizontalScroll, value),
.. self
}
}
#[inline]
pub fn always_insert_mode(self, value: bool) -> Self {
InputText {
flags: self.flags.with(ImGuiInputTextFlags_AlwaysInsertMode, value),
.. self
}
}
// TODO: boxed closure...?
// pub fn callback(self) -> Self { }
pub fn build(self) -> bool {
unsafe {
imgui_sys::igInputText(
self.label.as_ptr(),
// TODO: this is evil. Perhaps something else than &mut str is better
self.buf.as_ptr() as *mut i8,
self.buf.len() as size_t,
self.flags,
None,
ptr::null_mut())
}
}
}

View File

@ -1,87 +0,0 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::{Ui, ImStr};
#[must_use]
pub struct Menu<'ui, 'p> {
label: ImStr<'p>,
enabled: bool,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> Menu<'ui, 'p> {
pub fn new(label: ImStr<'p>) -> Self {
Menu {
label: label,
enabled: true,
_phantom: PhantomData
}
}
#[inline]
pub fn enabled(self, enabled: bool) -> Self {
Menu {
enabled: enabled,
.. self
}
}
pub fn build<F: FnOnce()>(self, f: F) {
let render = unsafe { imgui_sys::igBeginMenu(self.label.as_ptr(), self.enabled) };
if render {
f();
unsafe { imgui_sys::igEndMenu() };
}
}
}
#[must_use]
pub struct MenuItem<'ui, 'p> {
label: ImStr<'p>,
shortcut: Option<ImStr<'p>>,
selected: Option<&'p mut bool>,
enabled: bool,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> MenuItem<'ui, 'p> {
pub fn new(label: ImStr<'p>) -> Self {
MenuItem {
label: label,
shortcut: None,
selected: None,
enabled: true,
_phantom: PhantomData
}
}
#[inline]
pub fn shortcut(self, shortcut: ImStr<'p>) -> Self {
MenuItem {
shortcut: Some(shortcut),
.. self
}
}
#[inline]
pub fn selected(self, selected: &'p mut bool) -> Self {
MenuItem {
selected: Some(selected),
.. self
}
}
#[inline]
pub fn enabled(self, enabled: bool) -> Self {
MenuItem {
enabled: enabled,
.. self
}
}
pub fn build(self) -> bool {
let label = self.label.as_ptr();
let shortcut = self.shortcut.map(|x| x.as_ptr()).unwrap_or(ptr::null());
let selected = self.selected.map(|x| x as *mut bool).unwrap_or(ptr::null_mut());
let enabled = self.enabled;
unsafe {
imgui_sys::igMenuItemPtr(label, shortcut, selected, enabled)
}
}
}

View File

@ -1,91 +0,0 @@
use imgui_sys;
use std::marker::PhantomData;
use super::{Ui, ImStr};
// TODO: Consider using Range, even though it is half-open
#[must_use]
pub struct SliderInt<'ui, 'p> {
label: ImStr<'p>,
value: &'p mut i32,
min: i32,
max: i32,
display_format: ImStr<'p>,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> SliderInt<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut i32, min: i32, max: i32) -> Self {
SliderInt {
label: label,
value: value,
min: min,
max: max,
display_format: unsafe { ImStr::from_bytes_unchecked(b"%.0f\0") },
_phantom: PhantomData
}
}
#[inline]
pub fn display_format(self, display_format: ImStr<'p>) -> Self {
SliderInt {
display_format: display_format,
.. self
}
}
pub fn build(self) -> bool {
unsafe {
imgui_sys::igSliderInt(self.label.as_ptr(), self.value, self.min, self.max,
self.display_format.as_ptr()
)
}
}
}
#[must_use]
pub struct SliderFloat<'ui, 'p> {
label: ImStr<'p>,
value: &'p mut f32,
min: f32,
max: f32,
display_format: ImStr<'p>,
power: f32,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> SliderFloat<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut f32, min: f32, max: f32) -> Self {
SliderFloat {
label: label,
value: value,
min: min,
max: max,
display_format: unsafe { ImStr::from_bytes_unchecked(b"%.3f\0") },
power: 1.0,
_phantom: PhantomData
}
}
#[inline]
pub fn display_format(self, display_format: ImStr<'p>) -> Self {
SliderFloat {
display_format: display_format,
.. self
}
}
#[inline]
pub fn power(self, power: f32) -> Self {
SliderFloat {
power: power,
.. self
}
}
pub fn build(self) -> bool {
unsafe {
imgui_sys::igSliderFloat(self.label.as_ptr(), self.value, self.min, self.max,
self.display_format.as_ptr(),
self.power
)
}
}
}

View File

@ -1,56 +0,0 @@
use imgui_sys;
use std::marker::PhantomData;
use super::{Ui, ImGuiSetCond, ImStr};
#[must_use]
pub struct TreeNode<'ui, 'p> {
id: ImStr<'p>,
label: Option<ImStr<'p>>,
opened: bool,
opened_cond: ImGuiSetCond,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> TreeNode<'ui, 'p> {
pub fn new(id: ImStr<'p>) -> Self {
TreeNode {
id: id,
label: None,
opened: false,
opened_cond: ImGuiSetCond::empty(),
_phantom: PhantomData
}
}
#[inline]
pub fn label(self, label: ImStr<'p>) -> Self {
TreeNode {
label: Some(label),
.. self
}
}
#[inline]
pub fn opened(self, opened: bool, cond: ImGuiSetCond) -> Self {
TreeNode {
opened: opened,
opened_cond: cond,
.. self
}
}
pub fn build<F: FnOnce()>(self, f: F) {
let render = unsafe {
if !self.opened_cond.is_empty() {
imgui_sys::igSetNextTreeNodeOpened(self.opened, self.opened_cond);
}
imgui_sys::igTreeNodeStr(
self.id.as_ptr(),
super::fmt_ptr(),
self.label.unwrap_or(self.id).as_ptr()
)
};
if render {
f();
unsafe { imgui_sys::igTreePop() };
}
}
}

View File

@ -1,57 +0,0 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::{Ui, ImStr};
#[must_use]
pub struct CollapsingHeader<'ui, 'p> {
label: ImStr<'p>,
str_id: Option<ImStr<'p>>,
display_frame: bool,
default_open: bool,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> CollapsingHeader<'ui, 'p> {
pub fn new(label: ImStr<'p>) -> Self {
CollapsingHeader {
label: label,
str_id: None,
display_frame: true,
default_open: false,
_phantom: PhantomData
}
}
#[inline]
pub fn str_id(self, str_id: ImStr<'p>) -> Self {
CollapsingHeader {
str_id: Some(str_id),
.. self
}
}
#[inline]
pub fn display_frame(self, display_frame: bool) -> Self {
CollapsingHeader {
display_frame: display_frame,
.. self
}
}
#[inline]
pub fn default_open(self, default_open: bool) -> Self {
CollapsingHeader {
default_open: default_open,
.. self
}
}
pub fn build(self) -> bool {
unsafe {
imgui_sys::igCollapsingHeader(
self.label.as_ptr(),
self.str_id.map(|x| x.as_ptr()).unwrap_or(ptr::null()),
self.display_frame,
self.default_open
)
}
}
}

View File

@ -1,200 +0,0 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::{
Ui,
ImGuiSetCond,
ImGuiWindowFlags,
ImGuiWindowFlags_NoTitleBar, ImGuiWindowFlags_NoResize, ImGuiWindowFlags_NoMove,
ImGuiWindowFlags_NoScrollbar, ImGuiWindowFlags_NoScrollWithMouse, ImGuiWindowFlags_NoCollapse,
ImGuiWindowFlags_AlwaysAutoResize, ImGuiWindowFlags_ShowBorders,
ImGuiWindowFlags_NoSavedSettings, ImGuiWindowFlags_NoInputs, ImGuiWindowFlags_MenuBar,
ImGuiWindowFlags_HorizontalScrollbar, ImGuiWindowFlags_NoFocusOnAppearing,
ImGuiWindowFlags_NoBringToFrontOnFocus,
ImStr, ImVec2
};
#[must_use]
pub struct Window<'ui, 'p> {
pos: (f32, f32),
pos_cond: ImGuiSetCond,
size: (f32, f32),
size_cond: ImGuiSetCond,
name: ImStr<'p>,
opened: Option<&'p mut bool>,
bg_alpha: f32,
flags: ImGuiWindowFlags,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> Window<'ui, 'p> {
pub fn new(name: ImStr<'p>) -> Window<'ui, 'p> {
Window {
pos: (0.0, 0.0),
pos_cond: ImGuiSetCond::empty(),
size: (0.0, 0.0),
size_cond: ImGuiSetCond::empty(),
name: name,
opened: None,
bg_alpha: -1.0,
flags: ImGuiWindowFlags::empty(),
_phantom: PhantomData
}
}
#[inline]
pub fn position(self, pos: (f32, f32), cond: ImGuiSetCond) -> Self {
Window {
pos: pos,
pos_cond: cond,
.. self
}
}
#[inline]
pub fn size(self, size: (f32, f32), cond: ImGuiSetCond) -> Self {
Window {
size: size,
size_cond: cond,
.. self
}
}
#[inline]
pub fn opened(self, opened: &'p mut bool) -> Self {
Window {
opened: Some(opened),
.. self
}
}
#[inline]
pub fn bg_alpha(self, bg_alpha: f32) -> Self {
Window {
bg_alpha: bg_alpha,
.. self
}
}
#[inline]
pub fn flags(self, flags: ImGuiWindowFlags) -> Self {
Window {
flags: flags,
.. self
}
}
#[inline]
pub fn title_bar(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoTitleBar, !value),
.. self
}
}
#[inline]
pub fn resizable(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoResize, !value),
.. self
}
}
#[inline]
pub fn movable(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoMove, !value),
.. self
}
}
#[inline]
pub fn scroll_bar(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoScrollbar, !value),
.. self
}
}
#[inline]
pub fn scrollable(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoScrollWithMouse, !value),
.. self
}
}
#[inline]
pub fn collapsible(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoCollapse, !value),
.. self
}
}
#[inline]
pub fn always_auto_resize(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_AlwaysAutoResize, value),
.. self
}
}
#[inline]
pub fn show_borders(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_ShowBorders, value),
.. self
}
}
#[inline]
pub fn save_settings(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoSavedSettings, !value),
.. self
}
}
#[inline]
pub fn inputs(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoInputs, !value),
.. self
}
}
#[inline]
pub fn menu_bar(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_MenuBar, value),
.. self
}
}
#[inline]
pub fn horizontal_scrollbar(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_HorizontalScrollbar, value),
.. self
}
}
#[inline]
pub fn no_focus_on_appearing(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoFocusOnAppearing, value),
.. self
}
}
#[inline]
pub fn no_bring_to_front_on_focus(self, value: bool) -> Self {
Window {
flags: self.flags.with(ImGuiWindowFlags_NoBringToFrontOnFocus, value),
.. self
}
}
pub fn build<F: FnOnce()>(self, f: F) {
let render = unsafe {
if !self.pos_cond.is_empty() {
imgui_sys::igSetNextWindowPos(self.pos.into(), self.pos_cond);
}
if !self.size_cond.is_empty() {
imgui_sys::igSetNextWindowSize(self.size.into(), self.size_cond);
}
imgui_sys::igBegin2(
self.name.as_ptr(),
self.opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
ImVec2::new(0.0, 0.0),
self.bg_alpha,
self.flags)
};
if render {
f();
}
unsafe { imgui_sys::igEnd() };
}
}