Crates.io | egui-controls |
lib.rs | egui-controls |
version | 0.1.1 |
source | src |
created_at | 2023-06-24 22:42:26.658492 |
updated_at | 2023-06-26 13:06:14.553694 |
description | Helps build a control panel with egui. |
homepage | |
repository | https://github.com/aalekhpatel07/egui-controls |
max_upload_size | |
id | 899155 |
size | 135,067 |
egui-controls
is a Rust library that provides a ControlPanel
proc-macro to generate a simple control panel interface using the egui immediate mode graphical user interface library.
You're implementing a Rust algorithm that has various tunable parameters, and would like to inspect the output by tweaking the parameters in real-time.
cargo add egui-controls
Suppose your typical config data that contains the parameters for the algorithm looks like this:
#[derive(Debug, Clone)]
pub struct CirclePackingAlgorithmConfig {
/// The radius of the circles to pack.
pub radius: f64,
/// If circles overlap, then how many should be allowed
/// to overlap at most.
pub max_overlap_count: usize,
/// Once we find the circles, label them with the
/// given name.
pub circle_label: String,
/// Some global constant that should definitely only take on this value.
pub non_changing_global_value: i8
}
/// Some initial values for the config that make sense.
impl Default for CirclePackingAlgorithmConfig {
fn default() -> Self {
Self {
radius: 12.0,
max_overlap_count: 10,
circle_label: "Some text".to_string(),
non_changing_global_value: 42
}
}
}
Now, just derive egui_controls::ControlPanel for your data, and
sprinkle in some #[control]
attributes on the fields you'd like to be interactive in the UI:
+ use egui_controls::ControlPanel;
- #[derive(Debug, Clone)]
+ #[derive(Debug, Clone, ControlPanel)]
pub struct CirclePackingAlgorithmConfig {
/// The radius of the circles to pack.
+ #[control(slider(2. ..= 15.0))]
pub radius: f64,
/// If circles overlap, then how many should be allowed
/// to overlap at most.
+ #[control(slider(0 ..= 20))]
pub max_overlap_count: usize,
/// Once we find the circles, label them with the
/// given name.
+ #[control(textbox)]
pub circle_label: String,
/// Some global constant that should definitely only take on this value.
pub non_changing_global_value: i8
}
Now, use config.ui(ui)
to embed that in any UI section you're building with eframe::egui
.
use eframe::{egui, Frame};
#[derive(Debug, Clone, Default)]
pub struct MyApp {
settings: CirclePackingAlgorithmConfig
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut Frame) {
egui::CentralPanel::default().show(ctx, |ui: &mut egui::Ui| {
// Embed the settings panel
// directly into your ui.
self.settings.ui(ui);
// Add this the struct's debug repr if you want
// to see the values getting updated as you tweak
// the settings via the ui.
ui.vertical(|ui| {
ui.code(format!("{:#?}", &self.settings));
});
});
}
}
// Write the usual eframe entrypoint.
pub fn main() {
let options = ::eframe::NativeOptions {
resizable: true,
initial_window_size: Some(::eframe::egui::vec2(2000.0, 500.0)),
..Default::default()
};
let app = MyApp::default();
::eframe::run_native("readme", options, Box::new(|_| Box::new(app))).unwrap();
}
This generates a simple control panel interface for the CirclePackingAlgorithmConfig
and we can tune the values via the sliders.
Note: You can run the readme
example to generate the same output.