Skip to content

Commit

Permalink
* add input_scalar
Browse files Browse the repository at this point in the history
* allow setting display format for input_float
  • Loading branch information
EmbersArc authored and sanbox-irl committed Oct 6, 2021
1 parent 36aed0e commit bb66413
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 14 deletions.
17 changes: 13 additions & 4 deletions imgui-examples/examples/test_window_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ struct State {
text_with_hint: String,
text_multiline: String,
i0: i32,
u0: u64,
d0: f64,
f0: f32,
vec2f: [f32; 2],
vec3f: [f32; 3],
Expand Down Expand Up @@ -95,7 +97,9 @@ impl Default for State {
text_with_hint,
text_multiline,
i0: 123,
u0: 1234,
f0: 0.001,
d0: 0.0001,
vec2f: [0.10, 0.20],
vec3f: [0.10, 0.20, 0.30],
vec2i: [10, 20],
Expand Down Expand Up @@ -538,15 +542,20 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
ui.input_int("input int", &mut state.i0).build();
// Drag::new("drag int").build(ui, &mut state.i0);
ui.input_float("input float", &mut state.f0)
.step(0.01)
.step_fast(1.0)
.build();
.step(0.01)
.step_fast(1.0)
.build();
Drag::new("drag float").range(-1.0, 1.0).speed(0.001).build(ui, &mut state.f0);
ui.input_float3("input float3", &mut state.vec3f)
.build();
.build();
ColorEdit3::new("color 1", &mut state.col1).build(ui);
ColorEdit4::new("color 2", &mut state.col2).build(ui);

ui.input_scalar("input scalar i64", &mut state.u0).build(ui);
ui.input_scalar("input scalar f64", &mut state.d0).build(ui);
ui.input_scalar_n("input scalar int array", &mut state.vec3i).build(ui);
ui.input_scalar_n("input scalar float array", &mut state.vec3f).build(ui);

TreeNode::new("Multi-component Widgets").build(ui, || {
ui.input_float2("input float2", &mut state.vec2f)
.build();
Expand Down
223 changes: 213 additions & 10 deletions imgui/src/input_widget.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use bitflags::bitflags;
use std::ops::Range;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;

use crate::internal::DataTypeKind;
use crate::math::*;
use crate::sys;
use crate::Ui;
Expand Down Expand Up @@ -514,11 +516,12 @@ impl<'ui, 'p, L: AsRef<str>> InputInt<'ui, 'p, L> {
}

#[must_use]
pub struct InputFloat<'ui, 'p, L> {
pub struct InputFloat<'ui, 'p, L, F = &'static str> {
label: L,
value: &'p mut f32,
step: f32,
step_fast: f32,
display_format: Option<F>,
flags: InputTextFlags,
ui: &'ui Ui,
}
Expand All @@ -530,19 +533,36 @@ impl<'ui, 'p, L: AsRef<str>> InputFloat<'ui, 'p, L> {
value,
step: 0.0,
step_fast: 0.0,
display_format: None,
flags: InputTextFlags::empty(),
ui,
}
}

pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat<'ui, 'p, L, F2> {
InputFloat {
value: self.value,
label: self.label,
step: self.step,
step_fast: self.step_fast,
display_format: Some(display_format),
flags: self.flags,
ui: self.ui,
}
}

pub fn build(self) -> bool {
let (one, two) = self
.ui
.scratch_txt_with_opt(self.label, self.display_format);

unsafe {
sys::igInputFloat(
self.ui.scratch_txt(self.label),
one,
self.value as *mut f32,
self.step,
self.step_fast,
b"%.3f\0".as_ptr() as *const _,
two,
self.flags.bits() as i32,
)
}
Expand All @@ -555,9 +575,10 @@ impl<'ui, 'p, L: AsRef<str>> InputFloat<'ui, 'p, L> {
macro_rules! impl_input_floatn {
($InputFloatN:ident, $MINT_TARGET:ty, $N:expr, $igInputFloatN:ident) => {
#[must_use]
pub struct $InputFloatN<'ui, 'p, L, T> {
pub struct $InputFloatN<'ui, 'p, L, T, F = &'static str> {
label: L,
value: &'p mut T,
display_format: Option<F>,
flags: InputTextFlags,
ui: &'ui Ui,
}
Expand All @@ -572,22 +593,35 @@ macro_rules! impl_input_floatn {
$InputFloatN {
label,
value,
display_format: None,
flags: InputTextFlags::empty(),
ui,
}
}

pub fn display_format<F2: AsRef<str>>(
self,
display_format: F2,
) -> $InputFloatN<'ui, 'p, L, T, F2> {
$InputFloatN {
label: self.label,
value: self.value,
display_format: Some(display_format),
flags: self.flags,
ui: self.ui,
}
}

pub fn build(self) -> bool {
let value: $MINT_TARGET = (*self.value).into();
let mut value: [f32; $N] = value.into();

let (one, two) = self
.ui
.scratch_txt_with_opt(self.label, self.display_format);

let changed = unsafe {
sys::$igInputFloatN(
self.ui.scratch_txt(self.label),
value.as_mut_ptr(),
b"%.3f\0".as_ptr() as *const _,
self.flags.bits() as i32,
)
sys::$igInputFloatN(one, value.as_mut_ptr(), two, self.flags.bits() as i32)
};

if changed {
Expand Down Expand Up @@ -661,6 +695,175 @@ impl_input_intn!(InputInt2, MintIVec2, 2, igInputInt2);
impl_input_intn!(InputInt3, MintIVec3, 3, igInputInt3);
impl_input_intn!(InputInt4, MintIVec4, 4, igInputInt4);

/// Builder for an input scalar widget.
#[must_use]
pub struct InputScalar<'ui, 'p, T, L, F = &'static str> {
value: &'p mut T,
label: L,
step: Option<T>,
step_fast: Option<T>,
display_format: Option<F>,
flags: InputTextFlags,
ui: &'ui Ui,
}

impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalar<'ui, 'p, T, L> {
/// Constructs a new input scalar builder.
#[doc(alias = "InputScalar", alias = "InputScalarN")]
pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self {
InputScalar {
value,
label,
step: None,
step_fast: None,
display_format: None,
flags: InputTextFlags::empty(),
ui,
}
}
}

impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalar<'ui, 'p, T, L, F> {
/// Sets the display format using *a C-style printf string*
pub fn display_format<F2: AsRef<str>>(
self,
display_format: F2,
) -> InputScalar<'ui, 'p, T, L, F2> {
InputScalar {
value: self.value,
label: self.label,
step: self.step,
step_fast: self.step_fast,
display_format: Some(display_format),
flags: self.flags,
ui: self.ui,
}
}
/// Builds an input scalar that is bound to the given value.
///
/// Returns true if the value was changed.
pub fn build(self, ui: &Ui) -> bool {
unsafe {
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);

sys::igInputScalar(
one,
T::KIND as i32,
self.value as *mut T as *mut c_void,
self.step
.as_ref()
.map(|step| step as *const T)
.unwrap_or(ptr::null()) as *const c_void,
self.step_fast
.as_ref()
.map(|step| step as *const T)
.unwrap_or(ptr::null()) as *const c_void,
two,
self.flags.bits() as i32,
)
}
}

#[inline]
pub fn step(mut self, value: T) -> Self {
self.step = Some(value);
self
}

#[inline]
pub fn step_fast(mut self, value: T) -> Self {
self.step_fast = Some(value);
self
}

impl_text_flags!(InputScalar);
}

/// Builder for an input scalar widget.
#[must_use]
pub struct InputScalarN<'ui, 'p, T, L, F = &'static str> {
values: &'p mut [T],
label: L,
step: Option<T>,
step_fast: Option<T>,
display_format: Option<F>,
flags: InputTextFlags,
ui: &'ui Ui,
}

impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalarN<'ui, 'p, T, L> {
/// Constructs a new input scalar builder.
#[doc(alias = "InputScalarN")]
pub fn new(ui: &'ui Ui, label: L, values: &'p mut [T]) -> Self {
InputScalarN {
values,
label,
step: None,
step_fast: None,
display_format: None,
flags: InputTextFlags::empty(),
ui,
}
}
}

impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalarN<'ui, 'p, T, L, F> {
/// Sets the display format using *a C-style printf string*
pub fn display_format<F2: AsRef<str>>(
self,
display_format: F2,
) -> InputScalarN<'ui, 'p, T, L, F2> {
InputScalarN {
values: self.values,
label: self.label,
step: self.step,
step_fast: self.step_fast,
display_format: Some(display_format),
flags: self.flags,
ui: self.ui,
}
}
/// Builds a horizontal array of multiple input scalars attached to the given slice.
///
/// Returns true if any value was changed.
pub fn build(self, ui: &Ui) -> bool {
unsafe {
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);

sys::igInputScalarN(
one,
T::KIND as i32,
self.values.as_mut_ptr() as *mut c_void,
self.values.len() as i32,
self.step
.as_ref()
.map(|step| step as *const T)
.unwrap_or(ptr::null()) as *const c_void,
self.step_fast
.as_ref()
.map(|step| step as *const T)
.unwrap_or(ptr::null()) as *const c_void,
two,
self.flags.bits() as i32,
)
}
}

#[inline]
pub fn step(mut self, value: T) -> Self {
self.step = Some(value);
self
}

#[inline]
pub fn step_fast(mut self, value: T) -> Self {
self.step_fast = Some(value);
self
}

impl_text_flags!(InputScalar);
}

bitflags!(
/// Callback flags for an `InputText` widget. These correspond to
/// the general textflags.
Expand Down
24 changes: 24 additions & 0 deletions imgui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,30 @@ impl<'ui> Ui {
{
InputInt4::new(self, label, value)
}
#[doc(alias = "InputScalar")]
pub fn input_scalar<'p, L, T>(
&'ui self,
label: L,
value: &'p mut T,
) -> InputScalar<'ui, 'p, T, L>
where
L: AsRef<str>,
T: internal::DataTypeKind,
{
InputScalar::new(self, label, value)
}
#[doc(alias = "InputScalarN")]
pub fn input_scalar_n<'p, L, T>(
&'ui self,
label: L,
values: &'p mut [T],
) -> InputScalarN<'ui, 'p, T, L>
where
L: AsRef<str>,
T: internal::DataTypeKind,
{
InputScalarN::new(self, label, values)
}
}

create_token!(
Expand Down

0 comments on commit bb66413

Please sign in to comment.