diff --git a/imgui-sys/src/lib.rs b/imgui-sys/src/lib.rs index 0660381..89535cc 100644 --- a/imgui-sys/src/lib.rs +++ b/imgui-sys/src/lib.rs @@ -77,6 +77,17 @@ impl From> for ImVec2 { } } +impl From> for ImVec4 { + fn from(o: mint::Vector4) -> Self { + Self { + x: o.x, + y: o.y, + z: o.z, + w: o.w, + } + } +} + impl ImVec4 { #[inline] pub const fn new(x: f32, y: f32, z: f32, w: f32) -> ImVec4 { diff --git a/imgui/src/color.rs b/imgui/src/color.rs index 5f7e07c..1d20157 100644 --- a/imgui/src/color.rs +++ b/imgui/src/color.rs @@ -1,3 +1,5 @@ +use crate::math::MintVec4; + /// Wraps u32 that represents a packed RGBA color. Mostly used by types in the /// low level custom drawing API, such as [`DrawListMut`](crate::DrawListMut). /// @@ -220,6 +222,12 @@ impl From for ImColor32 { } } +impl From for ImColor32 { + fn from(v: MintVec4) -> Self { + Self::from_rgba_f32s(v.x, v.y, v.z, v.w) + } +} + impl From<[f32; 4]> for ImColor32 { #[inline] fn from(v: [f32; 4]) -> Self { diff --git a/imgui/src/draw_list.rs b/imgui/src/draw_list.rs index e6882e5..27323b0 100644 --- a/imgui/src/draw_list.rs +++ b/imgui/src/draw_list.rs @@ -15,7 +15,7 @@ use bitflags::bitflags; -use crate::ImColor32; +use crate::{math::MintVec2, ImColor32}; use sys::ImDrawList; use super::Ui; @@ -214,7 +214,12 @@ impl<'ui> ChannelsSplit<'ui> { impl<'ui> DrawListMut<'ui> { /// Returns a line from point `p1` to `p2` with color `c`. #[doc(alias = "AddLine")] - pub fn add_line(&'ui self, p1: [f32; 2], p2: [f32; 2], c: C) -> Line<'ui> + pub fn add_line( + &'ui self, + p1: impl Into, + p2: impl Into, + c: C, + ) -> Line<'ui> where C: Into, { @@ -224,7 +229,12 @@ impl<'ui> DrawListMut<'ui> { /// Returns a rectangle whose upper-left corner is at point `p1` /// and lower-right corner is at point `p2`, with color `c`. #[doc(alias = "AddRectFilled", alias = "AddRect")] - pub fn add_rect(&'ui self, p1: [f32; 2], p2: [f32; 2], c: C) -> Rect<'ui> + pub fn add_rect( + &'ui self, + p1: impl Into, + p2: impl Into, + c: C, + ) -> Rect<'ui> where C: Into, { @@ -239,8 +249,8 @@ impl<'ui> DrawListMut<'ui> { #[doc(alias = "AddRectFilledMultiColor")] pub fn add_rect_filled_multicolor( &self, - p1: [f32; 2], - p2: [f32; 2], + p1: impl Into, + p2: impl Into, col_upr_left: C1, col_upr_right: C2, col_bot_right: C3, @@ -254,8 +264,8 @@ impl<'ui> DrawListMut<'ui> { unsafe { sys::ImDrawList_AddRectFilledMultiColor( self.draw_list, - p1.into(), - p2.into(), + p1.into().into(), + p2.into().into(), col_upr_left.into().into(), col_upr_right.into().into(), col_bot_right.into().into(), @@ -269,9 +279,9 @@ impl<'ui> DrawListMut<'ui> { #[doc(alias = "AddTriangleFilled", alias = "AddTriangle")] pub fn add_triangle( &'ui self, - p1: [f32; 2], - p2: [f32; 2], - p3: [f32; 2], + p1: impl Into, + p2: impl Into, + p3: impl Into, c: C, ) -> Triangle<'ui> where @@ -282,7 +292,12 @@ impl<'ui> DrawListMut<'ui> { /// Returns a circle with the given `center`, `radius` and `color`. #[doc(alias = "AddCircleFilled", alias = "AddCircle")] - pub fn add_circle(&'ui self, center: [f32; 2], radius: f32, color: C) -> Circle<'ui> + pub fn add_circle( + &'ui self, + center: impl Into, + radius: f32, + color: C, + ) -> Circle<'ui> where C: Into, { @@ -291,35 +306,39 @@ impl<'ui> DrawListMut<'ui> { /// Draw a text whose upper-left corner is at point `pos`. #[doc(alias = "AddText")] - pub fn add_text(&self, pos: [f32; 2], col: C, text: T) - where - C: Into, - T: AsRef, - { + pub fn add_text( + &self, + pos: impl Into, + col: impl Into, + text: impl AsRef, + ) { use std::os::raw::c_char; let text = text.as_ref(); unsafe { let start = text.as_ptr() as *const c_char; let end = (start as usize + text.len()) as *const c_char; - sys::ImDrawList_AddText_Vec2(self.draw_list, pos.into(), col.into().into(), start, end) + sys::ImDrawList_AddText_Vec2( + self.draw_list, + pos.into().into(), + col.into().into(), + start, + end, + ) } } /// Returns a Bezier curve stretching from `pos0` to `pos1`, whose /// curvature is defined by `cp0` and `cp1`. #[doc(alias = "AddBezier", alias = "AddBezierCubic")] - pub fn add_bezier_curve( + pub fn add_bezier_curve( &'ui self, - pos0: [f32; 2], - cp0: [f32; 2], - cp1: [f32; 2], - pos1: [f32; 2], - color: C, - ) -> BezierCurve<'ui> - where - C: Into, - { + pos0: impl Into, + cp0: impl Into, + cp1: impl Into, + pos1: impl Into, + color: impl Into, + ) -> BezierCurve<'ui> { BezierCurve::new(self, pos0, cp0, cp1, pos1, color) } @@ -328,11 +347,18 @@ impl<'ui> DrawListMut<'ui> { /// Clip all drawings done within the closure `f` in the given /// rectangle. #[doc(alias = "PushClipRect", alias = "PopClipRect")] - pub fn with_clip_rect(&self, min: [f32; 2], max: [f32; 2], f: F) + pub fn with_clip_rect(&self, min: impl Into, max: impl Into, f: F) where F: FnOnce(), { - unsafe { sys::ImDrawList_PushClipRect(self.draw_list, min.into(), max.into(), false) } + unsafe { + sys::ImDrawList_PushClipRect( + self.draw_list, + min.into().into(), + max.into().into(), + false, + ) + } f(); unsafe { sys::ImDrawList_PopClipRect(self.draw_list) } } @@ -343,11 +369,17 @@ impl<'ui> DrawListMut<'ui> { /// rectangle. Intersect with all clipping rectangle previously on /// the stack. #[doc(alias = "PushClipRect", alias = "PopClipRect")] - pub fn with_clip_rect_intersect(&self, min: [f32; 2], max: [f32; 2], f: F) - where + pub fn with_clip_rect_intersect( + &self, + min: impl Into, + max: impl Into, + f: F, + ) where F: FnOnce(), { - unsafe { sys::ImDrawList_PushClipRect(self.draw_list, min.into(), max.into(), true) } + unsafe { + sys::ImDrawList_PushClipRect(self.draw_list, min.into().into(), max.into().into(), true) + } f(); unsafe { sys::ImDrawList_PopClipRect(self.draw_list) } } @@ -376,8 +408,8 @@ impl<'ui> DrawListMut<'ui> { pub fn add_image( &'ui self, texture_id: TextureId, - p_min: [f32; 2], - p_max: [f32; 2], + p_min: impl Into, + p_max: impl Into, ) -> Image<'_> { Image::new(self, texture_id, p_min, p_max) } @@ -388,10 +420,10 @@ impl<'ui> DrawListMut<'ui> { pub fn add_image_quad( &'ui self, texture_id: TextureId, - p1: [f32; 2], - p2: [f32; 2], - p3: [f32; 2], - p4: [f32; 2], + p1: impl Into, + p2: impl Into, + p3: impl Into, + p4: impl Into, ) -> ImageQuad<'_> { ImageQuad::new(self, texture_id, p1, p2, p3, p4) } @@ -400,8 +432,8 @@ impl<'ui> DrawListMut<'ui> { pub fn add_image_rounded( &'ui self, texture_id: TextureId, - p_min: [f32; 2], - p_max: [f32; 2], + p_min: impl Into, + p_max: impl Into, rounding: f32, ) -> ImageRounded<'_> { ImageRounded::new(self, texture_id, p_min, p_max, rounding) @@ -419,13 +451,18 @@ pub struct Line<'ui> { } impl<'ui> Line<'ui> { - fn new(draw_list: &'ui DrawListMut<'_>, p1: [f32; 2], p2: [f32; 2], c: C) -> Self + fn new( + draw_list: &'ui DrawListMut<'_>, + p1: impl Into, + p2: impl Into, + c: C, + ) -> Self where C: Into, { Self { - p1, - p2, + p1: p1.into().into(), + p2: p2.into().into(), color: c.into(), thickness: 1.0, draw_list, @@ -466,13 +503,18 @@ pub struct Rect<'ui> { } impl<'ui> Rect<'ui> { - fn new(draw_list: &'ui DrawListMut<'_>, p1: [f32; 2], p2: [f32; 2], c: C) -> Self + fn new( + draw_list: &'ui DrawListMut<'_>, + p1: impl Into, + p2: impl Into, + c: C, + ) -> Self where C: Into, { Self { - p1, - p2, + p1: p1.into().into(), + p2: p2.into().into(), color: c.into(), rounding: 0.0, flags: DrawFlags::ROUND_CORNERS_ALL, @@ -569,18 +611,18 @@ pub struct Triangle<'ui> { impl<'ui> Triangle<'ui> { fn new( draw_list: &'ui DrawListMut<'_>, - p1: [f32; 2], - p2: [f32; 2], - p3: [f32; 2], + p1: impl Into, + p2: impl Into, + p3: impl Into, c: C, ) -> Self where C: Into, { Self { - p1, - p2, - p3, + p1: p1.into().into(), + p2: p2.into().into(), + p3: p3.into().into(), color: c.into(), thickness: 1.0, filled: false, @@ -641,12 +683,17 @@ pub struct Circle<'ui> { impl<'ui> Circle<'ui> { /// Typically constructed by [`DrawListMut::add_circle`] - pub fn new(draw_list: &'ui DrawListMut<'_>, center: [f32; 2], radius: f32, color: C) -> Self + pub fn new( + draw_list: &'ui DrawListMut<'_>, + center: impl Into, + radius: f32, + color: C, + ) -> Self where C: Into, { Self { - center, + center: center.into().into(), radius, color: color.into(), num_segments: 0, @@ -720,20 +767,20 @@ impl<'ui> BezierCurve<'ui> { /// Typically constructed by [`DrawListMut::add_bezier_curve`] pub fn new( draw_list: &'ui DrawListMut<'_>, - pos0: [f32; 2], - cp0: [f32; 2], - cp1: [f32; 2], - pos1: [f32; 2], + pos0: impl Into, + cp0: impl Into, + cp1: impl Into, + pos1: impl Into, c: C, ) -> Self where C: Into, { Self { - pos0, - cp0, - cp1, - pos1, + pos0: pos0.into().into(), + cp0: cp0.into().into(), + cp1: cp1.into().into(), + pos1: pos1.into().into(), color: c.into(), thickness: 1.0, num_segments: None, @@ -789,13 +836,13 @@ impl<'ui> Image<'ui> { pub fn new( draw_list: &'ui DrawListMut<'_>, texture_id: TextureId, - p_min: [f32; 2], - p_max: [f32; 2], + p_min: impl Into, + p_max: impl Into, ) -> Self { Self { texture_id, - p_min, - p_max, + p_min: p_min.into().into(), + p_max: p_max.into().into(), uv_min: [0.0, 0.0], uv_max: [1.0, 1.0], col: [1.0, 1.0, 1.0, 1.0].into(), @@ -804,13 +851,13 @@ impl<'ui> Image<'ui> { } /// Set uv_min (default `[0.0, 0.0]`) - pub fn uv_min(mut self, uv_min: [f32; 2]) -> Self { - self.uv_min = uv_min; + pub fn uv_min(mut self, uv_min: impl Into) -> Self { + self.uv_min = uv_min.into().into(); self } /// Set uv_max (default `[1.0, 1.0]`) - pub fn uv_max(mut self, uv_max: [f32; 2]) -> Self { - self.uv_max = uv_max; + pub fn uv_max(mut self, uv_max: impl Into) -> Self { + self.uv_max = uv_max.into().into(); self } @@ -862,17 +909,17 @@ impl<'ui> ImageQuad<'ui> { pub fn new( draw_list: &'ui DrawListMut<'_>, texture_id: TextureId, - p1: [f32; 2], - p2: [f32; 2], - p3: [f32; 2], - p4: [f32; 2], + p1: impl Into, + p2: impl Into, + p3: impl Into, + p4: impl Into, ) -> Self { Self { texture_id, - p1, - p2, - p3, - p4, + p1: p1.into().into(), + p2: p2.into().into(), + p3: p3.into().into(), + p4: p4.into().into(), uv1: [0.0, 0.0], uv2: [1.0, 0.0], uv3: [1.0, 1.0], @@ -890,11 +937,17 @@ impl<'ui> ImageQuad<'ui> { /// uv3: [1, 1], /// uv4: [0, 1], /// ``` - pub fn uv(mut self, uv1: [f32; 2], uv2: [f32; 2], uv3: [f32; 2], uv4: [f32; 2]) -> Self { - self.uv1 = uv1; - self.uv2 = uv2; - self.uv3 = uv3; - self.uv4 = uv4; + pub fn uv( + mut self, + uv1: impl Into, + uv2: impl Into, + uv3: impl Into, + uv4: impl Into, + ) -> Self { + self.uv1 = uv1.into().into(); + self.uv2 = uv2.into().into(); + self.uv3 = uv3.into().into(); + self.uv4 = uv4.into().into(); self } @@ -949,14 +1002,14 @@ impl<'ui> ImageRounded<'ui> { pub fn new( draw_list: &'ui DrawListMut<'_>, texture_id: TextureId, - p_min: [f32; 2], - p_max: [f32; 2], + p_min: impl Into, + p_max: impl Into, rounding: f32, ) -> Self { Self { texture_id, - p_min, - p_max, + p_min: p_min.into().into(), + p_max: p_max.into().into(), uv_min: [0.0, 0.0], uv_max: [1.0, 1.0], col: [1.0, 1.0, 1.0, 1.0].into(), @@ -967,13 +1020,13 @@ impl<'ui> ImageRounded<'ui> { } /// Set uv_min (default `[0.0, 0.0]`) - pub fn uv_min(mut self, uv_min: [f32; 2]) -> Self { - self.uv_min = uv_min; + pub fn uv_min(mut self, uv_min: impl Into) -> Self { + self.uv_min = uv_min.into().into(); self } /// Set uv_max (default `[1.0, 1.0]`) - pub fn uv_max(mut self, uv_max: [f32; 2]) -> Self { - self.uv_max = uv_max; + pub fn uv_max(mut self, uv_max: impl Into) -> Self { + self.uv_max = uv_max.into().into(); self } diff --git a/imgui/src/input_widget.rs b/imgui/src/input_widget.rs index ae6b618..6f07544 100644 --- a/imgui/src/input_widget.rs +++ b/imgui/src/input_widget.rs @@ -2,6 +2,7 @@ use bitflags::bitflags; use std::ops::Range; use std::os::raw::{c_char, c_int, c_void}; +use crate::math::*; use crate::sys; use crate::Ui; @@ -360,12 +361,12 @@ impl<'ui, 'p, L: AsRef> InputTextMultiline<'ui, 'p, L, PassthroughCallback> /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. - pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: [f32; 2]) -> Self { + pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: impl Into) -> Self { InputTextMultiline { label, buf, flags: InputTextFlags::CALLBACK_RESIZE, - size, + size: size.into().into(), callback_handler: PassthroughCallback, ui, } @@ -552,17 +553,22 @@ impl<'ui, 'p, L: AsRef> InputFloat<'ui, 'p, L> { } macro_rules! impl_input_floatn { - ($InputFloatN:ident, $N:expr, $igInputFloatN:ident) => { + ($InputFloatN:ident, $MINT_TARGET:ident, $N:expr, $igInputFloatN:ident) => { #[must_use] - pub struct $InputFloatN<'ui, 'p, L> { + pub struct $InputFloatN<'ui, 'p, L, T = [f32; $N]> { label: L, - value: &'p mut [f32; $N], + value: &'p mut T, flags: InputTextFlags, ui: &'ui Ui<'ui>, } - impl<'ui, 'p, L: AsRef> $InputFloatN<'ui, 'p, L> { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut [f32; $N]) -> Self { + impl<'ui, 'p, L, T> $InputFloatN<'ui, 'p, L, T> + where + L: AsRef, + T: From<$MINT_TARGET> + Copy, + $MINT_TARGET: From, + { + pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self { $InputFloatN { label, value, @@ -572,14 +578,24 @@ macro_rules! impl_input_floatn { } pub fn build(self) -> bool { - unsafe { + let value: $MINT_TARGET = $MINT_TARGET::from(*self.value); + let mut value: [f32; $N] = value.into(); + + let changed = unsafe { sys::$igInputFloatN( self.ui.scratch_txt(self.label), - self.value.as_mut_ptr(), + value.as_mut_ptr(), b"%.3f\0".as_ptr() as *const _, self.flags.bits() as i32, ) + }; + + if changed { + let value: $MINT_TARGET = value.into(); + *self.value = value.into(); } + + changed } impl_text_flags!($InputFloatN); @@ -587,22 +603,27 @@ macro_rules! impl_input_floatn { }; } -impl_input_floatn!(InputFloat2, 2, igInputFloat2); -impl_input_floatn!(InputFloat3, 3, igInputFloat3); -impl_input_floatn!(InputFloat4, 4, igInputFloat4); +impl_input_floatn!(InputFloat2, MintVec2, 2, igInputFloat2); +impl_input_floatn!(InputFloat3, MintVec3, 3, igInputFloat3); +impl_input_floatn!(InputFloat4, MintVec4, 4, igInputFloat4); macro_rules! impl_input_intn { - ($InputIntN:ident, $N:expr, $igInputIntN:ident) => { + ($InputIntN:ident, $MINT_TARGET:ident, $N:expr, $igInputIntN:ident) => { #[must_use] - pub struct $InputIntN<'ui, 'p, L> { + pub struct $InputIntN<'ui, 'p, L, T> { label: L, - value: &'p mut [i32; $N], + value: &'p mut T, flags: InputTextFlags, ui: &'ui Ui<'ui>, } - impl<'ui, 'p, L: AsRef> $InputIntN<'ui, 'p, L> { - pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut [i32; $N]) -> Self { + impl<'ui, 'p, L, T> $InputIntN<'ui, 'p, L, T> + where + L: AsRef, + T: From<$MINT_TARGET> + Copy, + $MINT_TARGET: From, + { + pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self { $InputIntN { label, value, @@ -612,13 +633,23 @@ macro_rules! impl_input_intn { } pub fn build(self) -> bool { - unsafe { + let value: $MINT_TARGET = $MINT_TARGET::from(*self.value); + let mut value: [i32; $N] = value.into(); + + let changed = unsafe { sys::$igInputIntN( self.ui.scratch_txt(self.label), - self.value.as_mut_ptr(), + value.as_mut_ptr(), self.flags.bits() as i32, ) + }; + + if changed { + let value: $MINT_TARGET = value.into(); + *self.value = value.into(); } + + changed } impl_text_flags!($InputIntN); @@ -626,9 +657,9 @@ macro_rules! impl_input_intn { }; } -impl_input_intn!(InputInt2, 2, igInputInt2); -impl_input_intn!(InputInt3, 3, igInputInt3); -impl_input_intn!(InputInt4, 4, igInputInt4); +impl_input_intn!(InputInt2, MintIVec2, 2, igInputInt2); +impl_input_intn!(InputInt3, MintIVec3, 3, igInputInt3); +impl_input_intn!(InputInt4, MintIVec4, 4, igInputInt4); bitflags!( /// Callback flags for an `InputText` widget. These correspond to diff --git a/imgui/src/layout.rs b/imgui/src/layout.rs index f039b17..b0cdd16 100644 --- a/imgui/src/layout.rs +++ b/imgui/src/layout.rs @@ -1,3 +1,4 @@ +use crate::math::MintVec2; use crate::sys; use crate::Ui; @@ -64,8 +65,8 @@ impl<'ui> Ui<'ui> { /// /// Can be used to move the cursor on the window. #[doc(alias = "Dummy")] - pub fn dummy(&self, size: [f32; 2]) { - unsafe { sys::igDummy(size.into()) } + pub fn dummy(&self, size: impl Into) { + unsafe { sys::igDummy(size.into().into()) } } /// Moves content position to the right by `Style::indent_spacing` @@ -126,8 +127,8 @@ impl<'ui> Ui<'ui> { /// /// This sets the point on which the next widget will be drawn. #[doc(alias = "SetCursorPos")] - pub fn set_cursor_pos(&self, pos: [f32; 2]) { - unsafe { sys::igSetCursorPos(pos.into()) }; + pub fn set_cursor_pos(&self, pos: impl Into) { + unsafe { sys::igSetCursorPos(pos.into().into()) }; } /// Returns the initial cursor position (in window coordinates) #[doc(alias = "GetCursorStartPos")] @@ -147,8 +148,8 @@ impl<'ui> Ui<'ui> { } /// Sets the cursor position (in absolute screen coordinates) #[doc(alias = "SetCursorScreenPos")] - pub fn set_cursor_screen_pos(&self, pos: [f32; 2]) { - unsafe { sys::igSetCursorScreenPos(pos.into()) } + pub fn set_cursor_screen_pos(&self, pos: impl Into) { + unsafe { sys::igSetCursorScreenPos(pos.into().into()) } } /// Vertically aligns text baseline so that it will align properly to regularly frame items. /// diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 73a0187..336b5da 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -48,6 +48,7 @@ pub use self::widget::tree::*; pub use self::window::child_window::*; pub use self::window::*; use internal::RawCast; +use math::*; #[macro_use] mod string; @@ -68,6 +69,7 @@ pub mod internal; mod io; mod layout; mod list_clipper; +mod math; mod plothistogram; mod plotlines; mod popups; @@ -81,7 +83,6 @@ mod test; mod utils; mod widget; mod window; -mod math; // Used by macros. Underscores are just to make it clear it's not part of the // public API. @@ -388,27 +389,43 @@ impl<'ui> Ui<'ui> { ) -> InputFloat<'ui, 'p, L> { InputFloat::new(self, label, value) } - pub fn input_float2<'p, L: AsRef>( + #[doc(alias = "InputFloat2")] + pub fn input_float2<'p, L, T>( &'ui self, label: L, - value: &'p mut [f32; 2], - ) -> InputFloat2<'ui, 'p, L> { + value: &'p mut T, + ) -> InputFloat2<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintVec2: From, + { InputFloat2::new(self, label, value) } #[doc(alias = "InputFloat3")] - pub fn input_float3<'p, L: AsRef>( + pub fn input_float3<'p, L, T>( &'ui self, label: L, - value: &'p mut [f32; 3], - ) -> InputFloat3<'ui, 'p, L> { + value: &'p mut T, + ) -> InputFloat3<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintVec3: From, + { InputFloat3::new(self, label, value) } #[doc(alias = "InputFloat4")] - pub fn input_float4<'p, L: AsRef>( + pub fn input_float4<'p, L, T>( &'ui self, label: L, - value: &'p mut [f32; 4], - ) -> InputFloat4<'ui, 'p, L> { + value: &'p mut T, + ) -> InputFloat4<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintVec4: From, + { InputFloat4::new(self, label, value) } #[doc(alias = "InputInt")] @@ -420,27 +437,30 @@ impl<'ui> Ui<'ui> { InputInt::new(self, label, value) } #[doc(alias = "InputInt2")] - pub fn input_int2<'p, L: AsRef>( - &'ui self, - label: L, - value: &'p mut [i32; 2], - ) -> InputInt2<'ui, 'p, L> { + pub fn input_int2<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt2<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintIVec2: From, + { InputInt2::new(self, label, value) } #[doc(alias = "InputInt3")] - pub fn input_int3<'p, L: AsRef>( - &'ui self, - label: L, - value: &'p mut [i32; 3], - ) -> InputInt3<'ui, 'p, L> { + pub fn input_int3<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt3<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintIVec3: From, + { InputInt3::new(self, label, value) } #[doc(alias = "InputInt4")] - pub fn input_int4<'p, L: AsRef>( - &'ui self, - label: L, - value: &'p mut [i32; 4], - ) -> InputInt4<'ui, 'p, L> { + pub fn input_int4<'p, L, T>(&'ui self, label: L, value: &'p mut T) -> InputInt4<'ui, 'p, L, T> + where + L: AsRef, + T: From + Copy, + MintIVec4: From, + { InputInt4::new(self, label, value) } } diff --git a/imgui/src/math.rs b/imgui/src/math.rs index fe71d1a..7f8ab0d 100644 --- a/imgui/src/math.rs +++ b/imgui/src/math.rs @@ -1,3 +1,7 @@ pub(crate) type MintVec2 = mint::Vector2; pub(crate) type MintVec3 = mint::Vector3; pub(crate) type MintVec4 = mint::Vector4; + +pub(crate) type MintIVec2 = mint::Vector2; +pub(crate) type MintIVec3 = mint::Vector3; +pub(crate) type MintIVec4 = mint::Vector4; diff --git a/imgui/src/plothistogram.rs b/imgui/src/plothistogram.rs index ef490a1..0822970 100644 --- a/imgui/src/plothistogram.rs +++ b/imgui/src/plothistogram.rs @@ -62,8 +62,8 @@ impl<'ui, 'p, Label: AsRef, Overlay: AsRef> PlotHistogram<'ui, 'p, Lab self } - pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self { - self.graph_size = graph_size; + pub fn graph_size(mut self, graph_size: impl Into) -> Self { + self.graph_size = graph_size.into().into(); self } diff --git a/imgui/src/plotlines.rs b/imgui/src/plotlines.rs index 5c57e8e..a4d8441 100644 --- a/imgui/src/plotlines.rs +++ b/imgui/src/plotlines.rs @@ -62,8 +62,8 @@ impl<'ui, 'p, Label: AsRef, Overlay: AsRef> PlotLines<'ui, 'p, Label, self } - pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self { - self.graph_size = graph_size; + pub fn graph_size(mut self, graph_size: impl Into) -> Self { + self.graph_size = graph_size.into().into(); self } diff --git a/imgui/src/stacks.rs b/imgui/src/stacks.rs index c5964a7..94fad58 100644 --- a/imgui/src/stacks.rs +++ b/imgui/src/stacks.rs @@ -5,6 +5,7 @@ use std::ptr; use crate::context::Context; use crate::fonts::atlas::FontId; use crate::internal::RawCast; +use crate::math::MintVec4; use crate::style::{StyleColor, StyleVar}; use crate::sys; use crate::{Id, Ui}; @@ -61,9 +62,9 @@ impl<'ui> Ui<'ui> { pub fn push_style_color( &self, style_color: StyleColor, - color: [f32; 4], + color: impl Into, ) -> ColorStackToken<'_> { - unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into()) }; + unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into().into()) }; ColorStackToken::new(self) } diff --git a/imgui/src/utils.rs b/imgui/src/utils.rs index a1f41e1..f26e875 100644 --- a/imgui/src/utils.rs +++ b/imgui/src/utils.rs @@ -2,7 +2,8 @@ use bitflags::bitflags; use crate::input::mouse::MouseButton; -use crate::style::{Style, StyleColor}; +use crate::math::MintVec2; +use crate::style::StyleColor; use crate::sys; use crate::Ui; @@ -143,13 +144,17 @@ impl<'ui> Ui<'ui> { impl<'ui> Ui<'ui> { /// Returns `true` if the rectangle (of given size, starting from cursor position) is visible #[doc(alias = "IsRectVisibleNil")] - pub fn is_cursor_rect_visible(&self, size: [f32; 2]) -> bool { - unsafe { sys::igIsRectVisible_Nil(size.into()) } + pub fn is_cursor_rect_visible(&self, size: impl Into) -> bool { + unsafe { sys::igIsRectVisible_Nil(size.into().into()) } } /// Returns `true` if the rectangle (in screen coordinates) is visible #[doc(alias = "IsRectVisibleNilVec2")] - pub fn is_rect_visible(&self, rect_min: [f32; 2], rect_max: [f32; 2]) -> bool { - unsafe { sys::igIsRectVisible_Vec2(rect_min.into(), rect_max.into()) } + pub fn is_rect_visible( + &self, + rect_min: impl Into, + rect_max: impl Into, + ) -> bool { + unsafe { sys::igIsRectVisible_Vec2(rect_min.into().into(), rect_max.into().into()) } } /// Returns the global imgui-rs time. /// @@ -173,19 +178,20 @@ impl<'ui> Ui<'ui> { pub fn style_color(&self, style_color: StyleColor) -> [f32; 4] { self.ctx.style()[style_color] } - /// Returns a shared reference to the current [`Style`]. - /// - /// ## Safety - /// - /// This function is tagged as `unsafe` because pushing via - /// [`push_style_color`](crate::Ui::push_style_color) or - /// [`push_style_var`](crate::Ui::push_style_var) or popping via - /// [`ColorStackToken::pop`](crate::ColorStackToken::pop) or - /// [`StyleStackToken::pop`](crate::StyleStackToken::pop) will modify the values in the returned - /// shared reference. Therefore, you should not retain this reference across calls to push and - /// pop. The [`clone_style`](Ui::clone_style) version may instead be used to avoid `unsafe`. - #[doc(alias = "GetStyle")] - pub unsafe fn style(&self) -> &Style { - self.ctx.style() - } +} + +/// Returns a shared reference to the current [`Style`]. +/// +/// ## Safety +/// +/// This function is tagged as `unsafe` because pushing via +/// [`push_style_color`](crate::Ui::push_style_color) or +/// [`push_style_var`](crate::Ui::push_style_var) or popping via +/// [`ColorStackToken::pop`](crate::ColorStackToken::pop) or +/// [`StyleStackToken::pop`](crate::StyleStackToken::pop) will modify the values in the returned +/// shared reference. Therefore, you should not retain this reference across calls to push and +/// pop. The [`clone_style`](Ui::clone_style) version may instead be used to avoid `unsafe`. +#[doc(alias = "GetStyle")] +pub unsafe fn style(&self) -> &Style { + self.ctx.style() } diff --git a/imgui/src/widget/image.rs b/imgui/src/widget/image.rs index dd4c58b..4e2d115 100644 --- a/imgui/src/widget/image.rs +++ b/imgui/src/widget/image.rs @@ -1,5 +1,7 @@ use std::os::raw::c_void; +use crate::math::MintVec2; +use crate::math::MintVec4; use crate::render::renderer::TextureId; use crate::sys; use crate::Ui; @@ -19,10 +21,10 @@ pub struct Image { impl Image { /// Creates a new image builder with the given texture and size #[doc(alias = "Image")] - pub const fn new(texture_id: TextureId, size: [f32; 2]) -> Image { + pub fn new(texture_id: TextureId, size: impl Into) -> Image { Image { texture_id, - size, + size: size.into().into(), uv0: [0.0, 0.0], uv1: [1.0, 1.0], tint_col: [1.0, 1.0, 1.0, 1.0], @@ -30,28 +32,29 @@ impl Image { } } /// Sets the image size - pub const fn size(mut self, size: [f32; 2]) -> Self { - self.size = size; + #[deprecated(note = "just set the size in the `new` constructor.")] + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } /// Sets uv0 (default `[0.0, 0.0]`) - pub const fn uv0(mut self, uv0: [f32; 2]) -> Self { - self.uv0 = uv0; + pub fn uv0(mut self, uv0: impl Into) -> Self { + self.uv0 = uv0.into().into(); self } /// Sets uv1 (default `[1.0, 1.0]`) - pub const fn uv1(mut self, uv1: [f32; 2]) -> Self { - self.uv1 = uv1; + pub fn uv1(mut self, uv1: impl Into) -> Self { + self.uv1 = uv1.into().into(); self } /// Sets the tint color (default: no tint color) - pub const fn tint_col(mut self, tint_col: [f32; 4]) -> Self { - self.tint_col = tint_col; + pub fn tint_col(mut self, tint_col: impl Into) -> Self { + self.tint_col = tint_col.into().into(); self } /// Sets the border color (default: no border) - pub const fn border_col(mut self, border_col: [f32; 4]) -> Self { - self.border_col = border_col; + pub fn border_col(mut self, border_col: impl Into) -> Self { + self.border_col = border_col.into().into(); self } /// Builds the image @@ -85,10 +88,10 @@ pub struct ImageButton { impl ImageButton { /// Creates a new image button builder with the given texture and size #[doc(alias = "ImageButton")] - pub fn new(texture_id: TextureId, size: [f32; 2]) -> ImageButton { + pub fn new(texture_id: TextureId, size: impl Into) -> ImageButton { ImageButton { texture_id, - size, + size: size.into().into(), uv0: [0.0, 0.0], uv1: [1.0, 1.0], frame_padding: -1, @@ -96,19 +99,21 @@ impl ImageButton { tint_col: [1.0, 1.0, 1.0, 1.0], } } + /// Sets the image button size - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = size; + #[deprecated(note = "just set the size in the `new` constructor.")] + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } /// Sets uv0 (default `[0.0, 0.0]`) - pub fn uv0(mut self, uv0: [f32; 2]) -> Self { - self.uv0 = uv0; + pub fn uv0(mut self, uv0: impl Into) -> Self { + self.uv0 = uv0.into().into(); self } /// Sets uv1 (default `[1.0, 1.0]`) - pub fn uv1(mut self, uv1: [f32; 2]) -> Self { - self.uv1 = uv1; + pub fn uv1(mut self, uv1: impl Into) -> Self { + self.uv1 = uv1.into().into(); self } /// Sets the frame padding (default: uses frame padding from style). @@ -121,13 +126,13 @@ impl ImageButton { self } /// Sets the background color (default: no background color) - pub fn background_col(mut self, bg_col: [f32; 4]) -> Self { - self.bg_col = bg_col; + pub fn background_col(mut self, bg_col: impl Into) -> Self { + self.bg_col = bg_col.into().into(); self } /// Sets the tint color (default: no tint color) - pub fn tint_col(mut self, tint_col: [f32; 4]) -> Self { - self.tint_col = tint_col; + pub fn tint_col(mut self, tint_col: impl Into) -> Self { + self.tint_col = tint_col.into().into(); self } /// Builds the image button diff --git a/imgui/src/widget/list_box.rs b/imgui/src/widget/list_box.rs index 0485e6d..922d871 100644 --- a/imgui/src/widget/list_box.rs +++ b/imgui/src/widget/list_box.rs @@ -8,7 +8,7 @@ use crate::Ui; #[must_use] pub struct ListBox { label: T, - size: sys::ImVec2, + size: [f32; 2], } impl> ListBox { @@ -17,7 +17,7 @@ impl> ListBox { pub fn new(label: T) -> ListBox { ListBox { label, - size: sys::ImVec2::zero(), + size: [0.0, 0.0], } } @@ -28,8 +28,8 @@ impl> ListBox { /// /// Default: [0.0, 0.0], in which case the combobox calculates a sensible width and height #[inline] - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = sys::ImVec2::new(size[0], size[1]); + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } /// Creates a list box and starts appending to it. @@ -40,7 +40,8 @@ impl> ListBox { /// Returns `None` if the list box is not open and no content should be rendered. #[must_use] pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option> { - let should_render = unsafe { sys::igBeginListBox(ui.scratch_txt(self.label), self.size) }; + let should_render = + unsafe { sys::igBeginListBox(ui.scratch_txt(self.label), self.size.into()) }; if should_render { Some(ListBoxToken::new(ui)) } else { diff --git a/imgui/src/widget/misc.rs b/imgui/src/widget/misc.rs index e54e678..f79e128 100644 --- a/imgui/src/widget/misc.rs +++ b/imgui/src/widget/misc.rs @@ -1,6 +1,7 @@ use bitflags::bitflags; use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not}; +use crate::math::MintVec2; use crate::sys; use crate::{Direction, Ui}; @@ -38,8 +39,8 @@ impl<'ui> Ui<'ui> { /// Setting `size` as `[0.0, 0.0]` will size the button to the label's width in /// the current style. #[doc(alias = "Button")] - pub fn button_with_size(&self, label: impl AsRef, size: [f32; 2]) -> bool { - unsafe { sys::igButton(self.scratch_txt(label), size.into()) } + pub fn button_with_size(&self, label: impl AsRef, size: impl Into) -> bool { + unsafe { sys::igButton(self.scratch_txt(label), size.into().into()) } } /// Renders a small clickable button that is easy to embed in text. /// @@ -52,8 +53,8 @@ impl<'ui> Ui<'ui> { /// /// Returns true if this button was clicked. #[doc(alias = "InvisibleButton")] - pub fn invisible_button(&self, id: impl AsRef, size: [f32; 2]) -> bool { - unsafe { sys::igInvisibleButton(self.scratch_txt(id), size.into(), 0) } + pub fn invisible_button(&self, id: impl AsRef, size: impl Into) -> bool { + unsafe { sys::igInvisibleButton(self.scratch_txt(id), size.into().into(), 0) } } /// Renders a widget with button behaviour without the visual look. /// @@ -62,10 +63,16 @@ impl<'ui> Ui<'ui> { pub fn invisible_button_flags( &self, id: impl AsRef, - size: [f32; 2], + size: impl Into, flags: ButtonFlags, ) -> bool { - unsafe { sys::igInvisibleButton(self.scratch_txt(id), size.into(), flags.bits() as i32) } + unsafe { + sys::igInvisibleButton( + self.scratch_txt(id), + size.into().into(), + flags.bits() as i32, + ) + } } /// Renders a square button with an arrow shape. /// diff --git a/imgui/src/widget/progress_bar.rs b/imgui/src/widget/progress_bar.rs index dd6cba2..eb641ef 100644 --- a/imgui/src/widget/progress_bar.rs +++ b/imgui/src/widget/progress_bar.rs @@ -1,3 +1,4 @@ +use crate::math::MintVec2; use crate::sys; // use crate::ImStr; use crate::Ui; @@ -55,8 +56,8 @@ impl> ProgressBar { /// Negative values will automatically align to the end of the axis, zero will let the progress /// bar choose a size, and positive values will use the given size. #[inline] - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = size; + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } diff --git a/imgui/src/widget/selectable.rs b/imgui/src/widget/selectable.rs index ef0c172..48eceaa 100644 --- a/imgui/src/widget/selectable.rs +++ b/imgui/src/widget/selectable.rs @@ -1,5 +1,6 @@ use bitflags::bitflags; +use crate::math::MintVec2; use crate::sys; use crate::Ui; @@ -100,8 +101,8 @@ impl> Selectable { /// - `> 0.0`: use given height /// - `= 0.0`: use label height #[inline] - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = size; + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } /// Builds the selectable. diff --git a/imgui/src/widget/slider.rs b/imgui/src/widget/slider.rs index 231dd6b..5b7d1c9 100644 --- a/imgui/src/widget/slider.rs +++ b/imgui/src/widget/slider.rs @@ -2,6 +2,7 @@ use bitflags::bitflags; use std::os::raw::c_void; use crate::internal::DataTypeKind; +use crate::math::MintVec2; use crate::sys; use crate::Ui; @@ -161,10 +162,10 @@ where /// It is safe, though up to C++ Dear ImGui, on how to handle when /// `min > max`. #[doc(alias = "VSliderScalar")] - pub fn new(label: Label, size: [f32; 2], min: Data, max: Data) -> Self { + pub fn new(label: Label, size: impl Into, min: Data, max: Data) -> Self { VerticalSlider { label, - size, + size: size.into().into(), min, max, display_format: None, diff --git a/imgui/src/widget/text.rs b/imgui/src/widget/text.rs index 7273ec4..99bb0d4 100644 --- a/imgui/src/widget/text.rs +++ b/imgui/src/widget/text.rs @@ -1,5 +1,6 @@ use std::os::raw::c_char; +use crate::math::MintVec4; // use crate::string::ImStr; use crate::style::StyleColor; use crate::Ui; @@ -24,7 +25,7 @@ impl<'ui> Ui<'ui> { } } /// Renders simple text using the given text color - pub fn text_colored>(&self, color: [f32; 4], text: T) { + pub fn text_colored>(&self, color: impl Into, text: T) { let style = self.push_style_color(StyleColor::Text, color); self.text(text); style.end(); diff --git a/imgui/src/window/child_window.rs b/imgui/src/window/child_window.rs index 741c657..8b83df4 100644 --- a/imgui/src/window/child_window.rs +++ b/imgui/src/window/child_window.rs @@ -1,5 +1,6 @@ use std::f32; +use crate::math::MintVec2; use crate::sys; use crate::window::WindowFlags; use crate::Ui; @@ -47,8 +48,8 @@ impl<'ui, Label: AsRef> ChildWindow<'ui, Label> { /// - `= 0.0`: use remaining host window size /// - `< 0.0`: use remaining host window size minus abs(size) #[inline] - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = size; + pub fn size(mut self, size: impl Into) -> Self { + self.size = size.into().into(); self } /// Sets the window content size, which can be used to enforce scrollbars. @@ -57,8 +58,8 @@ impl<'ui, Label: AsRef> ChildWindow<'ui, Label> { /// 0.0 to leave the size automatic. #[inline] #[doc(alias = "SetNextWindowContentSize")] - pub fn content_size(mut self, size: [f32; 2]) -> Self { - self.content_size = size; + pub fn content_size(mut self, size: impl Into) -> Self { + self.content_size = size.into().into(); self } /// Sets the window focused state, which can be used to bring the window to front