From 05b9eb1df9291753e1d48495b599dce055c66d7d Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Wed, 16 Jul 2025 01:17:51 +0300 Subject: [PATCH] added background arc --- examples/example_knob.rs | 6 ++++-- src/lib.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/examples/example_knob.rs b/examples/example_knob.rs index 2f7595a..685c716 100644 --- a/examples/example_knob.rs +++ b/examples/example_knob.rs @@ -47,7 +47,8 @@ impl eframe::App for KnobExample { egui::Color32::from_rgb(60, 60, 60), egui::Color32::from_rgb(150, 150, 150), egui::Color32::from_rgb(200, 200, 200), - ), + ) + .with_background_arc(false), ) .changed() { @@ -70,7 +71,8 @@ impl eframe::App for KnobExample { .with_size(50.0) .with_font_size(14.0) .with_stroke_width(3.0) - .with_step(0.1), + .with_step(0.1) + .with_background_arc(false), ); ui.add( diff --git a/src/lib.rs b/src/lib.rs index 95c4510..0a4ef64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,8 @@ pub struct Knob<'a> { label_offset: f32, label_format: Box String>, step: Option, + drag_sensitivity: f32, + show_background_arc: bool, /// Minimum angle in radians. /// Specifies the lower bound of the knob's rotation. @@ -86,6 +88,8 @@ impl<'a> Knob<'a> { // Hardcode those two angles to ENSURE backward compatibility min_angle: -std::f32::consts::PI, max_angle: std::f32::consts::PI * 0.5, + drag_sensitivity: 0.005, + show_background_arc: true, } } @@ -196,6 +200,10 @@ impl<'a> Knob<'a> { self.step = Some(step); self } + pub fn with_background_arc(mut self, enabled: bool) -> Self { + self.show_background_arc = enabled; + self + } // Private fn compute_angle(&self) -> f32 { if self.min == self.max { @@ -240,7 +248,7 @@ impl Widget for Knob<'_> { if response.dragged() { let delta = response.drag_delta().y; let range = self.max - self.min; - let step = self.step.unwrap_or(range * 0.005); + let step = self.step.unwrap_or(range * self.drag_sensitivity); let new_value = (*self.value - delta * step).clamp(self.min, self.max); *self.value = if let Some(step) = self.step { @@ -281,6 +289,28 @@ impl Widget for Knob<'_> { painter.circle_stroke(center, radius, Stroke::new(self.stroke_width, knob_color)); + // Background arc (indicating full range) + if self.show_background_arc { + let arc_start = self.min_angle; + let arc_end = self.max_angle; + let segments = 64; + let arc_color = self.knob_color.gamma_multiply(0.5); // dimmed background arc + let arc_radius = radius * 0.8; + let mut points = Vec::with_capacity(segments + 1); + + for i in 0..=segments { + let t = i as f32 / segments as f32; + let angle = arc_start + (arc_end - arc_start) * t; + let pos = center + Vec2::angled(angle) * arc_radius; + points.push(pos); + } + + painter.add(egui::Shape::line( + points, + Stroke::new(self.stroke_width, arc_color), + )); + } + match self.style { KnobStyle::Wiper => { let pointer = center + Vec2::angled(angle) * (radius * 0.7);