Use mutable references instead of return values

It seems to be more ergonomical with the underlying library
This commit is contained in:
Joonas Javanainen 2015-08-21 00:08:40 +03:00
parent 9a37676580
commit eef67ddecc
8 changed files with 97 additions and 149 deletions

View File

@ -33,7 +33,7 @@ frame.window()
## Core design questions and current choices ## Core design questions and current choices
* Closures VS begin/end pairs (current choice: closures) * Closures VS begin/end pairs (current choice: closures)
* Mutable references VS return values (current choice: return values) * Mutable references VS return values (current choice: mutable references)
* Passing around Frame<'fr> VS passing around &'fr Frame (current choice: Frame<'fr>) * Passing around Frame<'fr> VS passing around &'fr Frame (current choice: Frame<'fr>)
* Splitting the API to smaller pieces VS all draw calls in Frame (current choice: all draw calls in Frame) * Splitting the API to smaller pieces VS all draw calls in Frame (current choice: all draw calls in Frame)
* Builder pattern for optional arguments VS something else (current choice: builder) * Builder pattern for optional arguments VS something else (current choice: builder)

View File

@ -23,7 +23,7 @@ fn main() {
} }
} }
fn hello_world<'a>(frame: &Frame<'a>) -> bool { fn hello_world<'a>(frame: &Frame<'a>) {
frame.window() frame.window()
.name(im_str!("Hello world")) .name(im_str!("Hello world"))
.size((300.0, 100.0), ImGuiSetCond_FirstUseEver) .size((300.0, 100.0), ImGuiSetCond_FirstUseEver)

View File

@ -39,9 +39,8 @@ impl Support {
self.imgui.set_mouse_down(&[self.mouse_pressed.0, self.mouse_pressed.1, self.mouse_pressed.2, false, false]); self.imgui.set_mouse_down(&[self.mouse_pressed.0, self.mouse_pressed.1, self.mouse_pressed.2, false, false]);
} }
pub fn render<'fr, 'a: 'fr , F: FnMut(&Frame<'fr>) -> bool>( pub fn render<'fr, 'a: 'fr , F: FnMut(&Frame<'fr>)>(
&'a mut self, clear_color: (f32, f32, f32, f32), mut f: F) -> bool { &'a mut self, clear_color: (f32, f32, f32, f32), mut f: F) -> bool {
let mut result;
let now = SteadyTime::now(); let now = SteadyTime::now();
let delta = now - self.last_frame; let delta = now - self.last_frame;
let delta_f = delta.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0; let delta_f = delta.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0;
@ -55,7 +54,7 @@ impl Support {
let (width, height) = target.get_dimensions(); let (width, height) = target.get_dimensions();
let frame = self.imgui.frame(width, height, delta_f); let frame = self.imgui.frame(width, height, delta_f);
result = f(&frame); f(&frame);
self.renderer.render(&mut target, frame).unwrap(); self.renderer.render(&mut target, frame).unwrap();
target.finish().unwrap(); target.finish().unwrap();
@ -64,7 +63,7 @@ impl Support {
match event { match event {
Event::Closed | Event::Closed |
Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape)) Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape))
=> result = false, => return false,
Event::MouseMoved(pos) => self.mouse_pos = pos, Event::MouseMoved(pos) => self.mouse_pos = pos,
Event::MouseInput(state, MouseButton::Left) => Event::MouseInput(state, MouseButton::Left) =>
self.mouse_pressed.0 = state == ElementState::Pressed, self.mouse_pressed.0 = state == ElementState::Pressed,
@ -75,6 +74,6 @@ impl Support {
_ => () _ => ()
} }
} }
result true
} }
} }

View File

@ -75,7 +75,7 @@ impl Default for FileMenuState {
} }
struct AutoResizeState { struct AutoResizeState {
lines: usize lines: i32
} }
impl Default for AutoResizeState { impl Default for AutoResizeState {
@ -91,12 +91,13 @@ fn main() {
.. Default::default() .. Default::default()
}; };
let mut support = Support::init(); let mut support = Support::init();
let mut opened = true;
loop { loop {
let active = support.render(state.clear_color, |frame| { let active = support.render(state.clear_color, |frame| {
show_test_window(frame, &mut state) show_test_window(frame, &mut state, &mut opened);
}); });
if !active { break } if !active || !opened { break }
} }
} }
@ -119,25 +120,25 @@ fn show_user_guide<'a>(frame: &Frame<'a>) {
Use +- to subtract.")); Use +- to subtract."));
} }
fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State) -> bool { fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State, opened: &mut bool) {
if state.show_app_metrics { if state.show_app_metrics {
state.show_app_metrics = frame.show_metrics_window(); frame.show_metrics_window(&mut state.show_app_metrics);
} }
if state.show_app_main_menu_bar { show_example_app_main_menu_bar(frame, state) } if state.show_app_main_menu_bar { show_example_app_main_menu_bar(frame, state) }
if state.show_app_auto_resize { if state.show_app_auto_resize {
state.show_app_auto_resize = show_example_app_auto_resize(frame, &mut state.auto_resize_state); show_example_app_auto_resize(frame, &mut state.auto_resize_state, &mut state.show_app_auto_resize);
} }
if state.show_app_fixed_overlay { if state.show_app_fixed_overlay {
state.show_app_fixed_overlay = show_example_app_fixed_overlay(frame); show_example_app_fixed_overlay(frame, &mut state.show_app_fixed_overlay);
} }
if state.show_app_manipulating_window_title { if state.show_app_manipulating_window_title {
show_example_app_manipulating_window_title(frame); show_example_app_manipulating_window_title(frame);
} }
if state.show_app_about { if state.show_app_about {
state.show_app_about = frame.window() frame.window()
.name(im_str!("About ImGui")) .name(im_str!("About ImGui"))
.always_auto_resize(true) .always_auto_resize(true)
.closable(true) .opened(&mut state.show_app_about)
.build(|| { .build(|| {
frame.text(ImStr::from_str(&format!("ImGui {}", imgui::get_version()))); frame.text(ImStr::from_str(&format!("ImGui {}", imgui::get_version())));
frame.separator(); frame.separator();
@ -157,7 +158,7 @@ fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State) -> bool {
.menu_bar(!state.no_menu) .menu_bar(!state.no_menu)
.bg_alpha(state.bg_alpha) .bg_alpha(state.bg_alpha)
.size((550.0, 680.0), ImGuiSetCond_FirstUseEver) .size((550.0, 680.0), ImGuiSetCond_FirstUseEver)
.closable(true) .opened(opened)
.build(|| { .build(|| {
frame.text(im_str!("ImGui says hello.")); frame.text(im_str!("ImGui says hello."));
frame.menu_bar(|| { frame.menu_bar(|| {
@ -165,39 +166,28 @@ fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State) -> bool {
show_example_menu_file(frame, &mut state.file_menu); show_example_menu_file(frame, &mut state.file_menu);
}); });
frame.menu(im_str!("Examples")).build(|| { frame.menu(im_str!("Examples")).build(|| {
if frame.menu_item(im_str!("Main menu bar")).build() { frame.menu_item(im_str!("Main menu bar"))
state.show_app_main_menu_bar = !state.show_app_main_menu_bar; .selected(&mut state.show_app_main_menu_bar).build();
} frame.menu_item(im_str!("Console"))
if frame.menu_item(im_str!("Console")).build() { .selected(&mut state.show_app_console).build();
state.show_app_console = !state.show_app_console; frame.menu_item(im_str!("Simple layout"))
} .selected(&mut state.show_app_layout).build();
if frame.menu_item(im_str!("Simple layout")).build() { frame.menu_item(im_str!("Long text display"))
state.show_app_layout = !state.show_app_layout; .selected(&mut state.show_app_long_text).build();
} frame.menu_item(im_str!("Auto-resizing window"))
if frame.menu_item(im_str!("Long text display")).build() { .selected(&mut state.show_app_auto_resize).build();
state.show_app_long_text = !state.show_app_long_text; frame.menu_item(im_str!("Simple overlay"))
} .selected(&mut state.show_app_fixed_overlay).build();
if frame.menu_item(im_str!("Auto-resizing window")).build() { frame.menu_item(im_str!("Manipulating window title"))
state.show_app_auto_resize = !state.show_app_auto_resize; .selected(&mut state.show_app_manipulating_window_title).build();
} frame.menu_item(im_str!("Custom rendering"))
if frame.menu_item(im_str!("Simple overlay")).build() { .selected(&mut state.show_app_custom_rendering).build();
state.show_app_fixed_overlay = !state.show_app_fixed_overlay;
}
if frame.menu_item(im_str!("Manipulating window title")).build() {
state.show_app_manipulating_window_title =
!state.show_app_manipulating_window_title;
}
if frame.menu_item(im_str!("Custom rendering")).build() {
state.show_app_custom_rendering = !state.show_app_custom_rendering;
}
}); });
frame.menu(im_str!("Help")).build(|| { frame.menu(im_str!("Help")).build(|| {
if frame.menu_item(im_str!("Metrics")).build() { frame.menu_item(im_str!("Metrics"))
state.show_app_metrics = !state.show_app_metrics; .selected(&mut state.show_app_metrics).build();
} frame.menu_item(im_str!("About ImGui"))
if frame.menu_item(im_str!("About ImGui")).build() { .selected(&mut state.show_app_about).build();
state.show_app_about = !state.show_app_about;
}
}); });
}); });
frame.spacing(); frame.spacing();
@ -207,35 +197,18 @@ fn show_test_window<'a>(frame: &Frame<'a>, state: &mut State) -> bool {
} }
if frame.collapsing_header(im_str!("Window options")).build() { if frame.collapsing_header(im_str!("Window options")).build() {
if let Some(no_titlebar) = frame.checkbox(im_str!("no titlebar"), state.no_titlebar) { frame.checkbox(im_str!("no titlebar"), &mut state.no_titlebar);
state.no_titlebar = no_titlebar;
}
frame.same_line(150.0); frame.same_line(150.0);
if let Some(no_border) = frame.checkbox(im_str!("no border"), state.no_border) { frame.checkbox(im_str!("no border"), &mut state.no_border);
state.no_border = no_border;
}
frame.same_line(300.0); frame.same_line(300.0);
if let Some(no_resize) = frame.checkbox(im_str!("no resize"), state.no_resize) { frame.checkbox(im_str!("no resize"), &mut state.no_resize);
state.no_resize = no_resize; frame.checkbox(im_str!("no move"), &mut state.no_move);
}
if let Some(no_move) = frame.checkbox(im_str!("no move"), state.no_move) {
state.no_move = no_move;
}
frame.same_line(150.0); frame.same_line(150.0);
if let Some(no_scrollbar) = frame.checkbox(im_str!("no scrollbar"), state.no_scrollbar) { frame.checkbox(im_str!("no scrollbar"), &mut state.no_scrollbar);
state.no_scrollbar = no_scrollbar;
}
frame.same_line(300.0); frame.same_line(300.0);
if let Some(no_collapse) = frame.checkbox(im_str!("no collapse"), state.no_collapse) { frame.checkbox(im_str!("no collapse"), &mut state.no_collapse);
state.no_collapse = no_collapse; frame.checkbox(im_str!("no menu"), &mut state.no_menu);
} frame.slider_f32(im_str!("bg alpha"), &mut state.bg_alpha, 0.0, 1.0).build();
if let Some(no_menu) = frame.checkbox(im_str!("no menu"), state.no_menu) {
state.no_menu = no_menu;
}
if let Some(bg_alpha) = frame.slider_f32(im_str!("bg alpha"),
state.bg_alpha, 0.0, 1.0).build() {
state.bg_alpha = bg_alpha;
}
} }
}) })
} }
@ -246,21 +219,21 @@ fn show_example_app_main_menu_bar<'a>(frame: &Frame<'a>, state: &mut State) {
show_example_menu_file(frame, &mut state.file_menu); show_example_menu_file(frame, &mut state.file_menu);
}); });
frame.menu(im_str!("Edit")).build(|| { frame.menu(im_str!("Edit")).build(|| {
if frame.menu_item(im_str!("Undo")).shortcut(im_str!("CTRL+Z")).build() { } frame.menu_item(im_str!("Undo")).shortcut(im_str!("CTRL+Z")).build();
if frame.menu_item(im_str!("Redo")) frame.menu_item(im_str!("Redo"))
.shortcut(im_str!("CTRL+Y")).enabled(false).build() { } .shortcut(im_str!("CTRL+Y")).enabled(false).build();
frame.separator(); frame.separator();
if frame.menu_item(im_str!("Cut")).shortcut(im_str!("CTRL+X")).build() { } frame.menu_item(im_str!("Cut")).shortcut(im_str!("CTRL+X")).build();
if frame.menu_item(im_str!("Copy")).shortcut(im_str!("CTRL+C")).build() { } frame.menu_item(im_str!("Copy")).shortcut(im_str!("CTRL+C")).build();
if frame.menu_item(im_str!("Paste")).shortcut(im_str!("CTRL+V")).build() { } frame.menu_item(im_str!("Paste")).shortcut(im_str!("CTRL+V")).build();
}); });
}); });
} }
fn show_example_menu_file<'a>(frame: &Frame<'a>, state: &mut FileMenuState) { fn show_example_menu_file<'a>(frame: &Frame<'a>, state: &mut FileMenuState) {
frame.menu_item(im_str!("(dummy menu)")).enabled(false).build(); frame.menu_item(im_str!("(dummy menu)")).enabled(false).build();
if frame.menu_item(im_str!("New")).build() { } frame.menu_item(im_str!("New")).build();
if frame.menu_item(im_str!("Open")).shortcut(im_str!("Ctrl+O")).build() { } frame.menu_item(im_str!("Open")).shortcut(im_str!("Ctrl+O")).build();
frame.menu(im_str!("Open Recent")).build(|| { frame.menu(im_str!("Open Recent")).build(|| {
frame.menu_item(im_str!("fish_hat.c")).build(); frame.menu_item(im_str!("fish_hat.c")).build();
frame.menu_item(im_str!("fish_hat.inl")).build(); frame.menu_item(im_str!("fish_hat.inl")).build();
@ -273,13 +246,11 @@ fn show_example_menu_file<'a>(frame: &Frame<'a>, state: &mut FileMenuState) {
}); });
}); });
}); });
if frame.menu_item(im_str!("Save")).shortcut(im_str!("Ctrl+S")).build() { } frame.menu_item(im_str!("Save")).shortcut(im_str!("Ctrl+S")).build();
if frame.menu_item(im_str!("Save As..")).build() { } frame.menu_item(im_str!("Save As..")).build();
frame.separator(); frame.separator();
frame.menu(im_str!("Options")).build(|| { frame.menu(im_str!("Options")).build(|| {
if frame.menu_item(im_str!("Enabled")).selected(state.enabled).build() { frame.menu_item(im_str!("Enabled")).selected(&mut state.enabled).build();
state.enabled = !state.enabled;
}
// TODO // TODO
}); });
frame.menu(im_str!("Colors")).build(|| { frame.menu(im_str!("Colors")).build(|| {
@ -288,33 +259,31 @@ fn show_example_menu_file<'a>(frame: &Frame<'a>, state: &mut FileMenuState) {
frame.menu(im_str!("Disabled")).enabled(false).build(|| { frame.menu(im_str!("Disabled")).enabled(false).build(|| {
unreachable!(); unreachable!();
}); });
if frame.menu_item(im_str!("Checked")).selected(true).build() { } let mut checked = true;
if frame.menu_item(im_str!("Quit")).shortcut(im_str!("Alt+F4")).build() { } frame.menu_item(im_str!("Checked")).selected(&mut checked).build();
frame.menu_item(im_str!("Quit")).shortcut(im_str!("Alt+F4")).build();
} }
fn show_example_app_auto_resize<'a>(frame: &Frame<'a>, state: &mut AutoResizeState) -> bool { fn show_example_app_auto_resize<'a>(frame: &Frame<'a>, state: &mut AutoResizeState, opened: &mut bool) {
frame.window() frame.window()
.name(im_str!("Example: Auto-resizing window")) .name(im_str!("Example: Auto-resizing window"))
.closable(true) .opened(opened)
.always_auto_resize(true) .always_auto_resize(true)
.build(|| { .build(|| {
frame.text(im_str!("Window will resize every-frame to the size of its content. frame.text(im_str!("Window will resize every-frame to the size of its content.
Note that you probably don't want to query the window size to Note that you probably don't want to query the window size to
output your content because that would create a feedback loop.")); output your content because that would create a feedback loop."));
if let Some(lines) = frame.slider_i32(im_str!("Number of lines"), frame.slider_i32(im_str!("Number of lines"), &mut state.lines, 1, 20).build();
state.lines as i32, 1, 20).build() {
state.lines = lines as usize;
}
for i in 0 .. state.lines { for i in 0 .. state.lines {
frame.text(im_str!("{:2$}This is line {}", "", i, i * 4)); frame.text(im_str!("{:2$}This is line {}", "", i, i as usize * 4));
} }
}) })
} }
fn show_example_app_fixed_overlay<'a>(frame: &Frame<'a>) -> bool { fn show_example_app_fixed_overlay<'a>(frame: &Frame<'a>, opened: &mut bool) {
frame.window() frame.window()
.name(im_str!("Example: Fixed Overlay")) .name(im_str!("Example: Fixed Overlay"))
.closable(true) .opened(opened)
.bg_alpha(0.3) .bg_alpha(0.3)
.title_bar(false) .title_bar(false)
.resizable(false) .resizable(false)

View File

@ -208,19 +208,15 @@ impl<'fr> Frame<'fr> {
Ok(()) Ok(())
} }
pub fn show_user_guide(&self) { unsafe { ffi::igShowUserGuide() }; } pub fn show_user_guide(&self) { unsafe { ffi::igShowUserGuide() }; }
pub fn show_test_window(&self) -> bool { pub fn show_test_window(&self, opened: &mut bool) {
let mut opened = true;
unsafe { unsafe {
ffi::igShowTestWindow(&mut opened); ffi::igShowTestWindow(opened);
} }
opened
} }
pub fn show_metrics_window(&self) -> bool { pub fn show_metrics_window(&self, opened: &mut bool) {
let mut opened = true;
unsafe { unsafe {
ffi::igShowMetricsWindow(&mut opened); ffi::igShowMetricsWindow(opened);
} }
opened
} }
} }
@ -286,23 +282,19 @@ impl<'fr> Frame<'fr> {
pub fn collapsing_header<'p>(&self, label: ImStr<'p>) -> CollapsingHeader<'fr, 'p> { pub fn collapsing_header<'p>(&self, label: ImStr<'p>) -> CollapsingHeader<'fr, 'p> {
CollapsingHeader::new(label) CollapsingHeader::new(label)
} }
pub fn checkbox<'p>(&self, label: ImStr<'p>, value: bool) -> Option<bool> { pub fn checkbox<'p>(&self, label: ImStr<'p>, value: &'p mut bool) -> bool {
let mut result = value; unsafe { ffi::igCheckbox(label.as_ptr(), value) }
let changed = unsafe {
ffi::igCheckbox(label.as_ptr(), &mut result)
};
if changed { Some(result) } else { None }
} }
} }
// Widgets: Sliders // Widgets: Sliders
impl<'fr> Frame<'fr> { impl<'fr> Frame<'fr> {
pub fn slider_f32<'p>(&self, label: ImStr<'p>, pub fn slider_f32<'p>(&self, label: ImStr<'p>,
value: f32, min: f32, max: f32) -> SliderFloat<'fr, 'p> { value: &'p mut f32, min: f32, max: f32) -> SliderFloat<'fr, 'p> {
SliderFloat::new(label, value, min, max) SliderFloat::new(label, value, min, max)
} }
pub fn slider_i32<'p>(&self, label: ImStr<'p>, pub fn slider_i32<'p>(&self, label: ImStr<'p>,
value: i32, min: i32, max: i32) -> SliderInt<'fr, 'p> { value: &'p mut i32, min: i32, max: i32) -> SliderInt<'fr, 'p> {
SliderInt::new(label, value, min, max) SliderInt::new(label, value, min, max)
} }
} }

View File

@ -37,7 +37,7 @@ impl<'fr, 'p> Menu<'fr, 'p> {
pub struct MenuItem<'fr, 'p> { pub struct MenuItem<'fr, 'p> {
label: ImStr<'p>, label: ImStr<'p>,
shortcut: Option<ImStr<'p>>, shortcut: Option<ImStr<'p>>,
selected: bool, selected: Option<&'p mut bool>,
enabled: bool, enabled: bool,
_phantom: PhantomData<&'fr Frame<'fr>> _phantom: PhantomData<&'fr Frame<'fr>>
} }
@ -47,7 +47,7 @@ impl<'fr, 'p> MenuItem<'fr, 'p> {
MenuItem { MenuItem {
label: label, label: label,
shortcut: None, shortcut: None,
selected: false, selected: None,
enabled: true, enabled: true,
_phantom: PhantomData _phantom: PhantomData
} }
@ -60,9 +60,9 @@ impl<'fr, 'p> MenuItem<'fr, 'p> {
} }
} }
#[inline] #[inline]
pub fn selected(self, selected: bool) -> Self { pub fn selected(self, selected: &'p mut bool) -> Self {
MenuItem { MenuItem {
selected: selected, selected: Some(selected),
.. self .. self
} }
} }
@ -76,10 +76,10 @@ impl<'fr, 'p> MenuItem<'fr, 'p> {
pub fn build(self) -> bool { pub fn build(self) -> bool {
let label = self.label.as_ptr(); let label = self.label.as_ptr();
let shortcut = self.shortcut.map(|x| x.as_ptr()).unwrap_or(ptr::null()); let shortcut = self.shortcut.map(|x| x.as_ptr()).unwrap_or(ptr::null());
let selected = self.selected; let selected = self.selected.map(|x| x as *mut bool).unwrap_or(ptr::null_mut());
let enabled = self.enabled; let enabled = self.enabled;
unsafe { unsafe {
ffi::igMenuItem(label, shortcut, selected, enabled) ffi::igMenuItemPtr(label, shortcut, selected, enabled)
} }
} }
} }

View File

@ -1,4 +1,3 @@
use libc::{c_float, c_int};
use std::marker::PhantomData; use std::marker::PhantomData;
use super::ffi; use super::ffi;
@ -8,7 +7,7 @@ use super::{Frame, ImStr};
pub struct SliderInt<'fr, 'p> { pub struct SliderInt<'fr, 'p> {
label: ImStr<'p>, label: ImStr<'p>,
value: i32, value: &'p mut i32,
min: i32, min: i32,
max: i32, max: i32,
display_format: ImStr<'p>, display_format: ImStr<'p>,
@ -16,7 +15,7 @@ pub struct SliderInt<'fr, 'p> {
} }
impl<'fr, 'p> SliderInt<'fr, 'p> { impl<'fr, 'p> SliderInt<'fr, 'p> {
pub fn new(label: ImStr<'p>, value: i32, min: i32, max: i32) -> Self { pub fn new(label: ImStr<'p>, value: &'p mut i32, min: i32, max: i32) -> Self {
SliderInt { SliderInt {
label: label, label: label,
value: value, value: value,
@ -33,22 +32,18 @@ impl<'fr, 'p> SliderInt<'fr, 'p> {
.. self .. self
} }
} }
pub fn build(self) -> Option<i32> { pub fn build(self) -> bool {
let mut value = self.value; unsafe {
let changed = unsafe { ffi::igSliderInt(self.label.as_ptr(), self.value, self.min, self.max,
ffi::igSliderInt(self.label.as_ptr(),
&mut value,
self.min, self.max,
self.display_format.as_ptr() self.display_format.as_ptr()
) )
}; }
if changed { Some(value) } else { None }
} }
} }
pub struct SliderFloat<'fr, 'p> { pub struct SliderFloat<'fr, 'p> {
label: ImStr<'p>, label: ImStr<'p>,
value: f32, value: &'p mut f32,
min: f32, min: f32,
max: f32, max: f32,
display_format: ImStr<'p>, display_format: ImStr<'p>,
@ -57,7 +52,7 @@ pub struct SliderFloat<'fr, 'p> {
} }
impl<'fr, 'p> SliderFloat<'fr, 'p> { impl<'fr, 'p> SliderFloat<'fr, 'p> {
pub fn new(label: ImStr<'p>, value: f32, min: f32, max: f32) -> Self { pub fn new(label: ImStr<'p>, value: &'p mut f32, min: f32, max: f32) -> Self {
SliderFloat { SliderFloat {
label: label, label: label,
value: value, value: value,
@ -82,17 +77,13 @@ impl<'fr, 'p> SliderFloat<'fr, 'p> {
.. self .. self
} }
} }
pub fn build(self) -> Option<f32> { pub fn build(self) -> bool {
let mut value = self.value; unsafe {
let changed = unsafe { ffi::igSliderFloat(self.label.as_ptr(), self.value, self.min, self.max,
ffi::igSliderFloat(self.label.as_ptr(),
&mut value,
self.min, self.max,
self.display_format.as_ptr(), self.display_format.as_ptr(),
self.power self.power
) )
}; }
if changed { Some(value) } else { None }
} }
} }

View File

@ -1,4 +1,3 @@
use libc::c_float;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr; use std::ptr;
@ -20,7 +19,7 @@ pub struct Window<'fr, 'p> {
size: (f32, f32), size: (f32, f32),
size_cond: ImGuiSetCond, size_cond: ImGuiSetCond,
name: ImStr<'p>, name: ImStr<'p>,
closable: bool, opened: Option<&'p mut bool>,
bg_alpha: f32, bg_alpha: f32,
flags: ImGuiWindowFlags, flags: ImGuiWindowFlags,
_phantom: PhantomData<&'fr Frame<'fr>> _phantom: PhantomData<&'fr Frame<'fr>>
@ -34,7 +33,7 @@ impl<'fr, 'p> Window<'fr, 'p> {
size: (0.0, 0.0), size: (0.0, 0.0),
size_cond: ImGuiSetCond::empty(), size_cond: ImGuiSetCond::empty(),
name: unsafe { ImStr::from_bytes(b"Debug\0") }, name: unsafe { ImStr::from_bytes(b"Debug\0") },
closable: false, opened: None,
bg_alpha: -1.0, bg_alpha: -1.0,
flags: ImGuiWindowFlags::empty(), flags: ImGuiWindowFlags::empty(),
_phantom: PhantomData _phantom: PhantomData
@ -64,9 +63,9 @@ impl<'fr, 'p> Window<'fr, 'p> {
} }
} }
#[inline] #[inline]
pub fn closable(self, closable: bool) -> Self { pub fn opened(self, opened: &'p mut bool) -> Self {
Window { Window {
closable: closable, opened: Some(opened),
.. self .. self
} }
} }
@ -160,8 +159,7 @@ impl<'fr, 'p> Window<'fr, 'p> {
.. self .. self
} }
} }
pub fn build<F: FnOnce()>(self, f: F) -> bool { pub fn build<F: FnOnce()>(self, f: F) {
let mut opened = true;
let render = unsafe { let render = unsafe {
if !self.pos_cond.is_empty() { if !self.pos_cond.is_empty() {
ffi::igSetNextWindowPos(ImVec2::new(self.pos.0, self.pos.1), self.pos_cond); ffi::igSetNextWindowPos(ImVec2::new(self.pos.0, self.pos.1), self.pos_cond);
@ -170,7 +168,7 @@ impl<'fr, 'p> Window<'fr, 'p> {
ffi::igSetNextWindowSize(ImVec2::new(self.size.0, self.size.1), self.size_cond); ffi::igSetNextWindowSize(ImVec2::new(self.size.0, self.size.1), self.size_cond);
} }
ffi::igBegin2(self.name.as_ptr(), ffi::igBegin2(self.name.as_ptr(),
if self.closable { &mut opened } else { ptr::null_mut() }, self.opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
ImVec2::new(0.0, 0.0), self.bg_alpha, self.flags ImVec2::new(0.0, 0.0), self.bg_alpha, self.flags
) )
}; };
@ -178,6 +176,5 @@ impl<'fr, 'p> Window<'fr, 'p> {
f(); f();
} }
unsafe { ffi::igEnd() }; unsafe { ffi::igEnd() };
opened
} }
} }