diff --git a/implot-examples/examples-shared/src/line_plots.rs b/implot-examples/examples-shared/src/line_plots.rs index 57ea9e7..f00b419 100644 --- a/implot-examples/examples-shared/src/line_plots.rs +++ b/implot-examples/examples-shared/src/line_plots.rs @@ -62,6 +62,22 @@ pub fn show_two_yaxis_plot(ui: &Ui, plot_ui: &PlotUi) { }); } +pub fn show_axis_equal_plot(ui: &Ui, plot_ui: &PlotUi) { + ui.text(im_str!("This plot has axis equal set (1:1 aspect ratio).")); + let content_width = ui.window_content_region_width(); + Plot::new("Axis equal line plot") + // The size call could also be omitted, though the defaults don't consider window + // width, which is why we're not doing so here. + .size(content_width, 300.0) + .with_plot_flags(&(PlotFlags::NONE | PlotFlags::AXIS_EQUAL)) + .build(plot_ui, || { + // If this is called outside a plot build callback, the program will panic. + let x_positions = vec![0.1, 0.9]; + let y_positions = vec![0.1, 0.9]; + PlotLine::new("legend label").plot(&x_positions, &y_positions); + }); +} + pub fn show_configurable_plot(ui: &Ui, plot_ui: &PlotUi) { ui.text(im_str!( "This header demos what we can configure about plots." @@ -321,4 +337,7 @@ pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) { if CollapsingHeader::new(im_str!("Line plot: Multiple Y Axes")).build(&ui) { show_two_yaxis_plot(&ui, &plot_ui); } + if CollapsingHeader::new(im_str!("Line plot: \"Axis equal\"")).build(&ui) { + show_axis_equal_plot(&ui, &plot_ui); + } } diff --git a/implot-sys/src/bindings.rs b/implot-sys/src/bindings.rs index cb3d13f..54afcd7 100644 --- a/implot-sys/src/bindings.rs +++ b/implot-sys/src/bindings.rs @@ -33,56 +33,6 @@ pub type ImDrawCallback = ::std::option::Option< pub type ImDrawIdx = ::std::os::raw::c_ushort; #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct ImVector_ImDrawVert { - pub Size: ::std::os::raw::c_int, - pub Capacity: ::std::os::raw::c_int, - pub Data: *mut ImDrawVert, -} -#[test] -fn bindgen_test_layout_ImVector_ImDrawVert() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ImVector_ImDrawVert)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ImVector_ImDrawVert)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImDrawVert), - "::", - stringify!(Size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImDrawVert), - "::", - stringify!(Capacity) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImDrawVert), - "::", - stringify!(Data) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct ImVector_ImDrawChannel { pub Size: ::std::os::raw::c_int, pub Capacity: ::std::os::raw::c_int, @@ -133,56 +83,6 @@ fn bindgen_test_layout_ImVector_ImDrawChannel() { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct ImVector_ImTextureID { - pub Size: ::std::os::raw::c_int, - pub Capacity: ::std::os::raw::c_int, - pub Data: *mut ImTextureID, -} -#[test] -fn bindgen_test_layout_ImVector_ImTextureID() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ImVector_ImTextureID)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ImVector_ImTextureID)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImTextureID), - "::", - stringify!(Size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImTextureID), - "::", - stringify!(Capacity) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImTextureID), - "::", - stringify!(Data) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct ImVector_ImDrawCmd { pub Size: ::std::os::raw::c_int, pub Capacity: ::std::os::raw::c_int, @@ -233,56 +133,6 @@ fn bindgen_test_layout_ImVector_ImDrawCmd() { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct ImVector_ImVec4 { - pub Size: ::std::os::raw::c_int, - pub Capacity: ::std::os::raw::c_int, - pub Data: *mut ImVec4, -} -#[test] -fn bindgen_test_layout_ImVector_ImVec4() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ImVector_ImVec4)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ImVector_ImVec4)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImVec4), - "::", - stringify!(Size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImVec4), - "::", - stringify!(Capacity) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ImVector_ImVec4), - "::", - stringify!(Data) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct ImVector_ImDrawIdx { pub Size: ::std::os::raw::c_int, pub Capacity: ::std::os::raw::c_int, @@ -333,6 +183,106 @@ fn bindgen_test_layout_ImVector_ImDrawIdx() { } #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct ImVector_ImDrawVert { + pub Size: ::std::os::raw::c_int, + pub Capacity: ::std::os::raw::c_int, + pub Data: *mut ImDrawVert, +} +#[test] +fn bindgen_test_layout_ImVector_ImDrawVert() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(ImVector_ImDrawVert)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(ImVector_ImDrawVert)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImDrawVert), + "::", + stringify!(Size) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImDrawVert), + "::", + stringify!(Capacity) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImDrawVert), + "::", + stringify!(Data) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ImVector_ImTextureID { + pub Size: ::std::os::raw::c_int, + pub Capacity: ::std::os::raw::c_int, + pub Data: *mut ImTextureID, +} +#[test] +fn bindgen_test_layout_ImVector_ImTextureID() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(ImVector_ImTextureID)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(ImVector_ImTextureID)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImTextureID), + "::", + stringify!(Size) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImTextureID), + "::", + stringify!(Capacity) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImTextureID), + "::", + stringify!(Data) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct ImVector_ImVec2 { pub Size: ::std::os::raw::c_int, pub Capacity: ::std::os::raw::c_int, @@ -383,6 +333,56 @@ fn bindgen_test_layout_ImVector_ImVec2() { } #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct ImVector_ImVec4 { + pub Size: ::std::os::raw::c_int, + pub Capacity: ::std::os::raw::c_int, + pub Data: *mut ImVec4, +} +#[test] +fn bindgen_test_layout_ImVector_ImVec4() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(ImVector_ImVec4)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(ImVector_ImVec4)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Size as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImVec4), + "::", + stringify!(Size) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Capacity as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImVec4), + "::", + stringify!(Capacity) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).Data as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(ImVector_ImVec4), + "::", + stringify!(Data) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct ImVec2 { pub x: f32, pub y: f32, @@ -870,18 +870,20 @@ pub type ImPlotLocation = ::std::os::raw::c_int; pub type ImPlotOrientation = ::std::os::raw::c_int; pub type ImPlotYAxis = ::std::os::raw::c_int; pub const ImPlotFlags__ImPlotFlags_None: ImPlotFlags_ = 0; -pub const ImPlotFlags__ImPlotFlags_NoLegend: ImPlotFlags_ = 1; -pub const ImPlotFlags__ImPlotFlags_NoMenus: ImPlotFlags_ = 2; -pub const ImPlotFlags__ImPlotFlags_NoBoxSelect: ImPlotFlags_ = 4; -pub const ImPlotFlags__ImPlotFlags_NoMousePos: ImPlotFlags_ = 8; -pub const ImPlotFlags__ImPlotFlags_NoHighlight: ImPlotFlags_ = 16; -pub const ImPlotFlags__ImPlotFlags_NoChild: ImPlotFlags_ = 32; -pub const ImPlotFlags__ImPlotFlags_YAxis2: ImPlotFlags_ = 64; -pub const ImPlotFlags__ImPlotFlags_YAxis3: ImPlotFlags_ = 128; -pub const ImPlotFlags__ImPlotFlags_Query: ImPlotFlags_ = 256; -pub const ImPlotFlags__ImPlotFlags_Crosshairs: ImPlotFlags_ = 512; -pub const ImPlotFlags__ImPlotFlags_AntiAliased: ImPlotFlags_ = 1024; -pub const ImPlotFlags__ImPlotFlags_CanvasOnly: ImPlotFlags_ = 15; +pub const ImPlotFlags__ImPlotFlags_NoTitle: ImPlotFlags_ = 1; +pub const ImPlotFlags__ImPlotFlags_NoLegend: ImPlotFlags_ = 2; +pub const ImPlotFlags__ImPlotFlags_NoMenus: ImPlotFlags_ = 4; +pub const ImPlotFlags__ImPlotFlags_NoBoxSelect: ImPlotFlags_ = 8; +pub const ImPlotFlags__ImPlotFlags_NoMousePos: ImPlotFlags_ = 16; +pub const ImPlotFlags__ImPlotFlags_NoHighlight: ImPlotFlags_ = 32; +pub const ImPlotFlags__ImPlotFlags_NoChild: ImPlotFlags_ = 64; +pub const ImPlotFlags__ImPlotFlags_Equal: ImPlotFlags_ = 128; +pub const ImPlotFlags__ImPlotFlags_YAxis2: ImPlotFlags_ = 256; +pub const ImPlotFlags__ImPlotFlags_YAxis3: ImPlotFlags_ = 512; +pub const ImPlotFlags__ImPlotFlags_Query: ImPlotFlags_ = 1024; +pub const ImPlotFlags__ImPlotFlags_Crosshairs: ImPlotFlags_ = 2048; +pub const ImPlotFlags__ImPlotFlags_AntiAliased: ImPlotFlags_ = 4096; +pub const ImPlotFlags__ImPlotFlags_CanvasOnly: ImPlotFlags_ = 31; pub type ImPlotFlags_ = ::std::os::raw::c_uint; pub const ImPlotAxisFlags__ImPlotAxisFlags_None: ImPlotAxisFlags_ = 0; pub const ImPlotAxisFlags__ImPlotAxisFlags_NoGridLines: ImPlotAxisFlags_ = 1; @@ -945,9 +947,10 @@ pub const ImPlotStyleVar__ImPlotStyleVar_LegendInnerPadding: ImPlotStyleVar_ = 2 pub const ImPlotStyleVar__ImPlotStyleVar_LegendSpacing: ImPlotStyleVar_ = 21; pub const ImPlotStyleVar__ImPlotStyleVar_MousePosPadding: ImPlotStyleVar_ = 22; pub const ImPlotStyleVar__ImPlotStyleVar_AnnotationPadding: ImPlotStyleVar_ = 23; -pub const ImPlotStyleVar__ImPlotStyleVar_PlotDefaultSize: ImPlotStyleVar_ = 24; -pub const ImPlotStyleVar__ImPlotStyleVar_PlotMinSize: ImPlotStyleVar_ = 25; -pub const ImPlotStyleVar__ImPlotStyleVar_COUNT: ImPlotStyleVar_ = 26; +pub const ImPlotStyleVar__ImPlotStyleVar_FitPadding: ImPlotStyleVar_ = 24; +pub const ImPlotStyleVar__ImPlotStyleVar_PlotDefaultSize: ImPlotStyleVar_ = 25; +pub const ImPlotStyleVar__ImPlotStyleVar_PlotMinSize: ImPlotStyleVar_ = 26; +pub const ImPlotStyleVar__ImPlotStyleVar_COUNT: ImPlotStyleVar_ = 27; pub type ImPlotStyleVar_ = ::std::os::raw::c_uint; pub const ImPlotMarker__ImPlotMarker_None: ImPlotMarker_ = -1; pub const ImPlotMarker__ImPlotMarker_Circle: ImPlotMarker_ = 0; @@ -1136,6 +1139,7 @@ pub struct ImPlotStyle { pub LegendSpacing: ImVec2, pub MousePosPadding: ImVec2, pub AnnotationPadding: ImVec2, + pub FitPadding: ImVec2, pub PlotDefaultSize: ImVec2, pub PlotMinSize: ImVec2, pub Colors: [ImVec4; 24usize], @@ -1148,7 +1152,7 @@ pub struct ImPlotStyle { fn bindgen_test_layout_ImPlotStyle() { assert_eq!( ::std::mem::size_of::(), - 552usize, + 560usize, concat!("Size of: ", stringify!(ImPlotStyle)) ); assert_eq!( @@ -1397,8 +1401,18 @@ fn bindgen_test_layout_ImPlotStyle() { ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::())).PlotDefaultSize as *const _ as usize }, + unsafe { &(*(::std::ptr::null::())).FitPadding as *const _ as usize }, 148usize, + concat!( + "Offset of field: ", + stringify!(ImPlotStyle), + "::", + stringify!(FitPadding) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).PlotDefaultSize as *const _ as usize }, + 156usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1408,7 +1422,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).PlotMinSize as *const _ as usize }, - 156usize, + 164usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1418,7 +1432,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).Colors as *const _ as usize }, - 164usize, + 172usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1428,7 +1442,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).AntiAliasedLines as *const _ as usize }, - 548usize, + 556usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1438,7 +1452,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).UseLocalTime as *const _ as usize }, - 549usize, + 557usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1448,7 +1462,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).UseISO8601 as *const _ as usize }, - 550usize, + 558usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), @@ -1458,7 +1472,7 @@ fn bindgen_test_layout_ImPlotStyle() { ); assert_eq!( unsafe { &(*(::std::ptr::null::())).Use24HourClock as *const _ as usize }, - 551usize, + 559usize, concat!( "Offset of field: ", stringify!(ImPlotStyle), diff --git a/implot-sys/third-party/cimplot b/implot-sys/third-party/cimplot index a7760f2..e8b146b 160000 --- a/implot-sys/third-party/cimplot +++ b/implot-sys/third-party/cimplot @@ -1 +1 @@ -Subproject commit a7760f2f7557e15f50fe7916c9243b192345b38e +Subproject commit e8b146bf60b7edcbb963b01320c7685374536e27 diff --git a/src/lib.rs b/src/lib.rs index a7adf8e..5accc9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -229,6 +229,9 @@ pub enum StyleVar { MousePosPadding = sys::ImPlotStyleVar__ImPlotStyleVar_MousePosPadding, /// ImVec2, text padding around annotation labels AnnotationPadding = sys::ImPlotStyleVar__ImPlotStyleVar_AnnotationPadding, + /// ImVec2, additional fit padding as a percentage of the fit extents + /// (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y) + FitPadding = sys::ImPlotStyleVar__ImPlotStyleVar_FitPadding, /// ImVec2, default size used when ImVec2(0,0) is passed to BeginPlot PlotDefaultSize = sys::ImPlotStyleVar__ImPlotStyleVar_PlotDefaultSize, /// ImVec2, minimum size plot frame can be when shrunk diff --git a/src/plot.rs b/src/plot.rs index a588f3e..0bc9835 100644 --- a/src/plot.rs +++ b/src/plot.rs @@ -33,6 +33,8 @@ bitflags! { /// A child window region will not be used to capture mouse scroll (can boost performance /// for single ImGui window applications) const NO_CHILD = sys::ImPlotFlags__ImPlotFlags_NoChild; + /// Use an aspect ratio of 1:1 for the plot + const AXIS_EQUAL = sys::ImPlotFlags__ImPlotFlags_Equal; /// Enable a 2nd y axis const Y_AXIS_2 = sys::ImPlotFlags__ImPlotFlags_YAxis2; /// Enable a 3nd y axis @@ -133,12 +135,12 @@ pub struct Plot { y_tick_labels: [Option>; NUMBER_OF_Y_AXES], /// Whether to also show the default Y ticks when showing custom ticks or not show_y_default_ticks: [bool; NUMBER_OF_Y_AXES], - /// Orientation of the legend - legend_orientation: PlotOrientation, - /// Location of the legend - legend_location: PlotLocation, - /// Whether the legend is shown outside the plot - legend_outside_plot: bool, + /// Configuration for the legend, if specified. The tuple contains location, orientation + /// and a boolean (true means legend is outside of plot, false means within). If nothing + /// is set, implot's defaults are used. Note also that if these are set, then implot's + /// interactive legend configuration does not work because it is overridden by the settings + /// here. + legend_configuration: Option<(PlotLocation, PlotOrientation, bool)>, /// Flags relating to the plot TODO(4bb4) make those into bitflags plot_flags: sys::ImPlotFlags, /// Flags relating to the X axis of the plot TODO(4bb4) make those into bitflags @@ -172,9 +174,7 @@ impl Plot { y_tick_positions: [POS_NONE; NUMBER_OF_Y_AXES], y_tick_labels: [TICK_NONE; NUMBER_OF_Y_AXES], show_y_default_ticks: [false; NUMBER_OF_Y_AXES], - legend_location: PlotLocation::NorthWest, - legend_orientation: PlotOrientation::Vertical, - legend_outside_plot: false, + legend_configuration: None, plot_flags: PlotFlags::ANTIALIASED.bits() as sys::ImPlotFlags, x_flags: AxisFlags::NONE.bits() as sys::ImPlotAxisFlags, y_flags: [AxisFlags::NONE.bits() as sys::ImPlotAxisFlags; NUMBER_OF_Y_AXES], @@ -316,9 +316,7 @@ impl Plot { orientation: &PlotOrientation, outside: bool, ) -> Self { - self.legend_location = *location; - self.legend_orientation = *orientation; - self.legend_outside_plot = outside; + self.legend_configuration = Some((*location, *orientation, outside)); self } @@ -438,17 +436,20 @@ impl Plot { }; if should_render { - // Configure legend location. This has to be called between begin() and end(), - // but since only the last call to it actually affects the outcome, I'm adding - // it here instead of as a freestanding function. If this is too restrictive - // (for example, if you want to set the location based on code running _during_ - // the plotting for some reason), file an issue and we'll move it. - unsafe { - sys::ImPlot_SetLegendLocation( - self.legend_location as i32, - self.legend_orientation as i32, - self.legend_outside_plot, - ) + // Configure legend location, if one was set. This has to be called between begin() and + // end(), but since only the last call to it actually affects the outcome, I'm adding + // it here instead of as a freestanding function. If this is too restrictive (for + // example, if you want to set the location based on code running _during_ the plotting + // for some reason), file an issue and we'll move it. + if let Some(legend_config) = &self.legend_configuration { + // We introduce variables with typechecks here to safeguard against accidental + // changes in order in the config tuple + let location: PlotLocation = legend_config.0; + let orientation: PlotOrientation = legend_config.1; + let outside_plot: bool = legend_config.2; + unsafe { + sys::ImPlot_SetLegendLocation(location as i32, orientation as i32, outside_plot) + } } Some(PlotToken {