mirror of
https://github.com/obsqrbtz/egui_knob.git
synced 2026-04-08 20:19:17 +03:00
fix: Address PR feedback
Prevent division by zero when min equals max value Also improves angle calculations using TAU constant and adds NaN validation. Also fix doc
This commit is contained in:
@@ -122,7 +122,7 @@ impl eframe::App for KnobExample {
|
||||
);
|
||||
|
||||
ui.add(
|
||||
Knob::new(&mut self.blue_value, 0.0, 100.0, egui_knob::KnobStyle::Dot)
|
||||
Knob::new(&mut self.blue_value, 0.0, 100., egui_knob::KnobStyle::Dot)
|
||||
.with_label("Top", egui_knob::LabelPosition::Top)
|
||||
.with_colors(
|
||||
egui::Color32::from_rgb(30, 30, 80),
|
||||
|
||||
36
src/lib.rs
36
src/lib.rs
@@ -44,7 +44,16 @@ pub struct Knob<'a> {
|
||||
label_offset: f32,
|
||||
label_format: Box<dyn Fn(f32) -> String>,
|
||||
step: Option<f32>,
|
||||
|
||||
/// Minimum angle in radians.
|
||||
/// Specifies the lower bound of the knob's rotation.
|
||||
/// Expected range: 0.0 to TAU. Values outside this range are allowed if your use case requires it.
|
||||
min_angle: f32,
|
||||
|
||||
/// Maximum angle in radians.
|
||||
/// Specifies the upper bound of the knob's rotation.
|
||||
/// Can be any value > `min_angle`
|
||||
/// range `max_angle` - `min_angle` > TAU is allowed but will induce multi-turn
|
||||
max_angle: f32,
|
||||
}
|
||||
|
||||
@@ -73,6 +82,8 @@ impl<'a> Knob<'a> {
|
||||
label_offset: 1.0,
|
||||
label_format: Box::new(|v| format!("{:.2}", v)),
|
||||
step: None,
|
||||
|
||||
// Hardcode those two angles to ENSURE backward compatibility
|
||||
min_angle: -std::f32::consts::PI,
|
||||
max_angle: std::f32::consts::PI * 0.5,
|
||||
}
|
||||
@@ -81,7 +92,7 @@ impl<'a> Knob<'a> {
|
||||
/// Sets the angular sweep range of the knob
|
||||
///
|
||||
/// This controls where the knob starts and how far it can rotate. By default,
|
||||
/// knobs start at the bottom-left (135°) and sweep 270° clockwise to bottom-right.
|
||||
/// knobs start at the left (180°) and sweep 270° clockwise to bottom.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `start_angle_normalized` - Starting position as fraction of full circle:
|
||||
@@ -95,12 +106,20 @@ impl<'a> Knob<'a> {
|
||||
/// - `0.75` = three-quarter turn (270°)
|
||||
/// - `1.0` = full turn (360°)
|
||||
/// - Values > 1.0 create multi-turn knobs
|
||||
/// - Negative values are clamped to 0.0
|
||||
///
|
||||
/// Note: the start angle is offset by PI/2 so that `0.0` is at the bottom (6 o'clock)
|
||||
pub fn with_sweep_range(mut self, start_angle_normalized: f32, range: f32) -> Self {
|
||||
if start_angle_normalized.is_nan() || range.is_nan() {
|
||||
// Invalid input, return unchanged
|
||||
return self;
|
||||
}
|
||||
|
||||
self.min_angle =
|
||||
start_angle_normalized.rem_euclid(1.) * f32::consts::PI * 2. + f32::consts::PI / 2.;
|
||||
start_angle_normalized.rem_euclid(1.) * f32::consts::TAU + f32::consts::PI / 2.;
|
||||
|
||||
// A range of 1. represent a full turn
|
||||
self.max_angle = self.min_angle + range.max(0.) * 2. * f32::consts::PI;
|
||||
self.max_angle = self.min_angle + range.max(0.) * f32::consts::TAU;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -242,8 +261,15 @@ impl Widget for Knob<'_> {
|
||||
|
||||
let center = knob_rect.center();
|
||||
let radius = knob_size.x / 2.0;
|
||||
let angle = self.min_angle
|
||||
+ (*self.value - self.min) / (self.max - self.min) * (self.max_angle - self.min_angle);
|
||||
let angle = if self.min == self.max {
|
||||
// If min == max, just return min angle
|
||||
// That's a edge case, using a 0 range knob is pretty useless
|
||||
self.min_angle
|
||||
} else {
|
||||
self.min_angle
|
||||
+ (*self.value - self.min) / (self.max - self.min)
|
||||
* (self.max_angle - self.min_angle)
|
||||
};
|
||||
|
||||
painter.circle_stroke(
|
||||
center,
|
||||
|
||||
Reference in New Issue
Block a user