Refactored Plot building, various example updates
This commit is contained in:
parent
7d09c30892
commit
b832924fad
5 changed files with 114 additions and 42 deletions
|
@ -5,9 +5,10 @@
|
||||||
// for now, but expected to diverge from that over time.
|
// for now, but expected to diverge from that over time.
|
||||||
use std::{env, fs, io, path::Path};
|
use std::{env, fs, io, path::Path};
|
||||||
|
|
||||||
const CPP_FILES: [&str; 2] = [
|
const CPP_FILES: [&str; 3] = [
|
||||||
"third-party/cimplot/cimplot.cpp",
|
"third-party/cimplot/cimplot.cpp",
|
||||||
"third-party/cimplot/implot/implot.cpp",
|
"third-party/cimplot/implot/implot.cpp",
|
||||||
|
"third-party/cimplot/implot/implot_demo.cpp", // Could remove this if demo not used
|
||||||
];
|
];
|
||||||
|
|
||||||
fn assert_file_exists(path: &str) -> io::Result<()> {
|
fn assert_file_exists(path: &str) -> io::Result<()> {
|
||||||
|
|
105
src/lib.rs
105
src/lib.rs
|
@ -1,11 +1,30 @@
|
||||||
//! # Rust bindings to ImPlot
|
//! # Rust bindings to ImPlot
|
||||||
//!
|
//!
|
||||||
//! This crate contains idiomatic bindings to the C++ implot library, which
|
//! This crate contains idiomatic bindings to the C++ [implot library](https://github.com/epezent/implot),
|
||||||
//! use the bindings exposed by the `implot-sys` crate.
|
//! which use the bindings exposed by the `implot-sys` crate. An attempt is made to keep
|
||||||
|
//! documentation here somewhat self-contained, but when in doubt, the documentation of implot
|
||||||
|
//! itself (in particular also the demo code [here](https://github.com/epezent/implot/blob/master/implot_demo.cpp))
|
||||||
|
//! should help as well.
|
||||||
|
//!
|
||||||
|
//!
|
||||||
pub extern crate implot_sys as sys;
|
pub extern crate implot_sys as sys;
|
||||||
use sys::imgui::im_str;
|
use sys::imgui::im_str;
|
||||||
|
|
||||||
/// Struct to represent an ImPlot.
|
/// Struct to represent an ImPlot. This is the main construct used to contain all kinds of plots in ImPlot.
|
||||||
|
///
|
||||||
|
/// `Plot` is to be used (within an imgui window) with the following pattern:
|
||||||
|
/// ```rust
|
||||||
|
/// # // This doctest fails because we don't have an imgui context to run things in here
|
||||||
|
/// # use implot;
|
||||||
|
/// implot::Plot::new("my title")
|
||||||
|
/// .size(300.0, 200.0) // other things such as .x_label("some_label") can be added too
|
||||||
|
/// .build( || {
|
||||||
|
/// // Do things such as plotting lines
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// (If you are coming from the C++ implementation or the C bindings: build() calls both
|
||||||
|
/// begin() and end() internally)
|
||||||
pub struct Plot {
|
pub struct Plot {
|
||||||
/// Title of the plot, shown on top.
|
/// Title of the plot, shown on top.
|
||||||
title: String,
|
title: String,
|
||||||
|
@ -13,10 +32,10 @@ pub struct Plot {
|
||||||
x_label: String,
|
x_label: String,
|
||||||
/// Label of the y axis, shown on the left
|
/// Label of the y axis, shown on the left
|
||||||
y_label: String,
|
y_label: String,
|
||||||
/// Size of the plot in x direction, in pixels.
|
/// Size of the plot in x direction, in the same units imgui uses.
|
||||||
size_x: u32,
|
size_x: f32,
|
||||||
/// Size of the plot in y direction, in pixels.
|
/// Size of the plot in y direction, in the same units imgui uses.
|
||||||
size_y: u32,
|
size_y: f32,
|
||||||
/// Flags relating to the plot TODO(4bb4) make those into bitflags
|
/// Flags relating to the plot TODO(4bb4) make those into bitflags
|
||||||
plot_flags: sys::ImPlotFlags,
|
plot_flags: sys::ImPlotFlags,
|
||||||
/// Flags relating to the first x axis of the plot TODO(4bb4) make those into bitflags
|
/// Flags relating to the first x axis of the plot TODO(4bb4) make those into bitflags
|
||||||
|
@ -33,25 +52,48 @@ pub struct Plot {
|
||||||
|
|
||||||
impl Plot {
|
impl Plot {
|
||||||
/// Create a new plot with some defaults set. Does not draw anything yet.
|
/// Create a new plot with some defaults set. Does not draw anything yet.
|
||||||
pub fn new() -> Self {
|
pub fn new(title: &str) -> Self {
|
||||||
// TODO(4bb4) question these defaults, maybe remove some of them
|
// TODO(4bb4) question these defaults, maybe remove some of them
|
||||||
Self {
|
Self {
|
||||||
title: "".to_owned(),
|
title: title.to_owned(),
|
||||||
x_label: "".to_owned(),
|
x_label: "".to_owned(),
|
||||||
y_label: "".to_owned(),
|
y_label: "".to_owned(),
|
||||||
size_x: 400,
|
size_x: 400.0,
|
||||||
size_y: 400,
|
size_y: 400.0,
|
||||||
plot_flags: 0xFF,
|
plot_flags: 0xFF, // TODO(4bb4) define the defaults better
|
||||||
x_flags: 7,
|
x_flags: 7, // TODO(4bb4) define the defaults better
|
||||||
y_flags: 7,
|
y_flags: 7, // TODO(4bb4) define the defaults better
|
||||||
x2_flags: 0,
|
x2_flags: 0, // TODO(4bb4) define the defaults better
|
||||||
y2_flags: 0,
|
y2_flags: 0, // TODO(4bb4) define the defaults better
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the plot size, given as [size_x, size_y]. Units are the same as
|
||||||
|
/// what imgui uses. TODO(4b4) ... which is? I'm not sure it's pixels
|
||||||
|
#[inline]
|
||||||
|
pub fn size(mut self, size_x: f32, size_y: f32) -> Self {
|
||||||
|
self.size_x = size_x;
|
||||||
|
self.size_y = size_y;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the x label of the plot
|
||||||
|
#[inline]
|
||||||
|
pub fn x_label(mut self, label: &str) -> Self {
|
||||||
|
self.x_label = label.to_owned();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the y label of the plot
|
||||||
|
#[inline]
|
||||||
|
pub fn y_label(mut self, label: &str) -> Self {
|
||||||
|
self.y_label = label.to_owned();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempt to show the plot. Only do things with it and call `end()` after that
|
/// Attempt to show the plot. Only do things with it and call `end()` after that
|
||||||
/// if this returns `true`.
|
/// if this returns `true`. Not to be used directly, use `build` instead.
|
||||||
pub fn begin(&self) -> bool {
|
fn begin(&self) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::ImPlot_BeginPlot(
|
sys::ImPlot_BeginPlot(
|
||||||
im_str!("{}", self.title).as_ptr(),
|
im_str!("{}", self.title).as_ptr(),
|
||||||
|
@ -70,14 +112,25 @@ impl Plot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// End a previously-`begin()`ed plot. Only call if `begin()` returned `true`.
|
/// End (this) plot. This gets called from build()
|
||||||
pub fn end(&self) {
|
fn end(&self) {
|
||||||
unsafe { sys::ImPlot_EndPlot() }
|
unsafe { sys::ImPlot_EndPlot() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a window and runs a closure to construct the contents.
|
||||||
|
///
|
||||||
|
/// Note: the closure is not called if ImPlot::BeginPlot() returned
|
||||||
|
/// false - TODO(4bb4) figure out if this is if things are not rendered
|
||||||
|
pub fn build<F: FnOnce()>(self, f: F) {
|
||||||
|
if self.begin() {
|
||||||
|
f();
|
||||||
|
self.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(4bb4) convert to struct and add methods to set title and flags
|
// TODO(4bb4) convert to struct and add methods to set title and flags
|
||||||
/// Plot a line. Use this between Plot::begin() and Plot::end().
|
/// Plot a line. Use this in closures passed to [`Plot::build()`](struct.Plot.html#method.build)
|
||||||
pub fn plot_line(x: &Vec<f64>, y: &Vec<f64>, label: &str) {
|
pub fn plot_line(x: &Vec<f64>, y: &Vec<f64>, label: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
implot_sys::ImPlot_PlotLinedoublePtrdoublePtr(
|
implot_sys::ImPlot_PlotLinedoublePtrdoublePtr(
|
||||||
|
@ -90,3 +143,13 @@ pub fn plot_line(x: &Vec<f64>, y: &Vec<f64>, label: &str) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Show the demo window for poking around what functionality implot has to
|
||||||
|
/// offer. Note that not all of this is necessarily implemented in implot-rs
|
||||||
|
/// already - if you find something missing you'd really like, raise an issue.
|
||||||
|
// This requires implot_demo.cpp to be in the list of sources in implot-sys.
|
||||||
|
pub fn show_demo_window(show: &mut bool) {
|
||||||
|
unsafe {
|
||||||
|
implot_sys::ImPlot_ShowDemoWindow(show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "imgui-examples"
|
name = "implot-examples"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Joonas Javanainen <joonas.javanainen@gmail.com>", "imgui-rs contributors"]
|
authors = ["Sandro Merkli", "implot-rs contributors"]
|
||||||
description = "imgui crate examples using Glium backend"
|
description = "implot examples, with backend code from the imgui examples in imgui-examples"
|
||||||
homepage = "https://github.com/Gekkio/imgui-rs"
|
homepage = "https://github.com/4bb4/implot-rs"
|
||||||
repository = "https://github.com/Gekkio/imgui-rs"
|
repository = "https://github.com/4bb4/implot-rs"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
|
@ -5,30 +5,38 @@ mod support;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let system = support::init(file!());
|
let system = support::init(file!());
|
||||||
|
let mut showing_demo = false;
|
||||||
system.main_loop(move |_, ui| {
|
system.main_loop(move |_, ui| {
|
||||||
|
// Create the window from time imgui example, just... with an added plot
|
||||||
Window::new(im_str!("Hello world"))
|
Window::new(im_str!("Hello world"))
|
||||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
.size([430.0, 450.0], Condition::FirstUseEver)
|
||||||
.build(ui, || {
|
.build(ui, || {
|
||||||
ui.text(im_str!("Hello world!"));
|
ui.text(im_str!("Hello from implot-rs!"));
|
||||||
ui.text(im_str!("こんにちは世界!"));
|
|
||||||
ui.text(im_str!("This...is...imgui-rs!"));
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
let mouse_pos = ui.io().mouse_pos;
|
let mouse_pos = ui.io().mouse_pos;
|
||||||
ui.text(format!(
|
ui.text(format!(
|
||||||
"Mouse Position: ({:.1},{:.1})",
|
"Mouse Position: ({:.1},{:.1})",
|
||||||
mouse_pos[0], mouse_pos[1]
|
mouse_pos[0], mouse_pos[1]
|
||||||
));
|
));
|
||||||
|
ui.checkbox(im_str!("Show demo"), &mut showing_demo);
|
||||||
|
|
||||||
// Demo some implot stuff :D
|
// Draw a plot
|
||||||
let x_values = vec![1.0, 2.0, 4.0, 5.0];
|
implot::Plot::new("Demo plot")
|
||||||
let y_values = vec![1.0, 0.0, 0.0, 1.0];
|
.size(400.0, 300.0)
|
||||||
let plot = implot::Plot::new();
|
.x_label("awesome x label")
|
||||||
if plot.begin() {
|
.y_label("awesome y label")
|
||||||
|
.build(|| {
|
||||||
implot::plot_line(&vec![2.0, 2.0], &vec![2.0, 1.0], "Left eye");
|
implot::plot_line(&vec![2.0, 2.0], &vec![2.0, 1.0], "Left eye");
|
||||||
implot::plot_line(&vec![4.0, 4.0], &vec![2.0, 1.0], "Right eye");
|
implot::plot_line(&vec![4.0, 4.0], &vec![2.0, 1.0], "Right eye");
|
||||||
|
|
||||||
|
let x_values = vec![1.0, 2.0, 4.0, 5.0];
|
||||||
|
let y_values = vec![1.0, 0.0, 0.0, 1.0];
|
||||||
implot::plot_line(&x_values, &y_values, "Mouth");
|
implot::plot_line(&x_values, &y_values, "Mouth");
|
||||||
plot.end();
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if showing_demo {
|
||||||
|
implot::show_demo_window(&mut showing_demo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use glium::glutin::event::{Event, WindowEvent};
|
||||||
use glium::glutin::event_loop::{ControlFlow, EventLoop};
|
use glium::glutin::event_loop::{ControlFlow, EventLoop};
|
||||||
use glium::glutin::window::WindowBuilder;
|
use glium::glutin::window::WindowBuilder;
|
||||||
use glium::{Display, Surface};
|
use glium::{Display, Surface};
|
||||||
use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui};
|
use imgui::{Context, FontConfig, FontSource, Ui};
|
||||||
use imgui_glium_renderer::Renderer;
|
use imgui_glium_renderer::Renderer;
|
||||||
use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
Loading…
Reference in a new issue