Compare commits
1 commit
master
...
dancing-st
Author | SHA1 | Date | |
---|---|---|---|
![]() |
df937af2c5 |
1 changed files with 125 additions and 9 deletions
|
@ -1,13 +1,10 @@
|
|||
use egui::{containers::*, *};
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "persistence", serde(default))]
|
||||
pub struct DancingStrings {}
|
||||
|
||||
impl Default for DancingStrings {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
pub struct DancingStrings {
|
||||
two_notes: TwoNotes,
|
||||
}
|
||||
|
||||
impl super::Demo for DancingStrings {
|
||||
|
@ -27,6 +24,17 @@ impl super::Demo for DancingStrings {
|
|||
|
||||
impl super::View for DancingStrings {
|
||||
fn ui(&mut self, ui: &mut Ui) {
|
||||
self.dancing_ui(ui);
|
||||
ui.separator();
|
||||
self.two_notes.ui(ui);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.add(crate::__egui_github_link_file!());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl DancingStrings {
|
||||
fn dancing_ui(&mut self, ui: &mut Ui) {
|
||||
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
||||
ui.ctx().request_repaint();
|
||||
let time = ui.input().time;
|
||||
|
@ -62,8 +70,116 @@ impl super::View for DancingStrings {
|
|||
|
||||
ui.painter().extend(shapes);
|
||||
});
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.add(crate::__egui_github_link_file!());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "persistence", serde(default))]
|
||||
struct TwoNotes {
|
||||
height: f32,
|
||||
num_repeats: u32,
|
||||
rel_freqs: Vec<f32>,
|
||||
}
|
||||
|
||||
impl Default for TwoNotes {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
height: 75.0,
|
||||
num_repeats: 4,
|
||||
rel_freqs: vec![1.0, 3.0 / 2.0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TwoNotes {
|
||||
pub fn ui(&mut self, ui: &mut Ui) {
|
||||
self.canvas_frame_ui(ui);
|
||||
self.control_ui(ui);
|
||||
}
|
||||
|
||||
fn control_ui(&mut self, ui: &mut Ui) {
|
||||
let Self {
|
||||
height,
|
||||
num_repeats,
|
||||
rel_freqs,
|
||||
} = self;
|
||||
ui.style_mut().spacing.slider_width = 500.0;
|
||||
ui.add(Slider::f32(height, 10.0..=100.0).text("height"));
|
||||
ui.add(Slider::u32(num_repeats, 1..=10).text("num_repeats"));
|
||||
ui.add(Slider::f32(&mut rel_freqs[1], 1.0..=2.0).text("Frequency multiplier"));
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let fractions = [(1, 1), (6, 5), (5, 4), (4, 3), (3, 2), (2, 1)];
|
||||
for &(t, n) in &fractions {
|
||||
if ui.button(format!("{} / {}", t, n)).clicked() {
|
||||
rel_freqs[1] = (t as f32) / (n as f32);
|
||||
*num_repeats = n;
|
||||
}
|
||||
}
|
||||
});
|
||||
if ui.button("√2").clicked() {
|
||||
rel_freqs[1] = 2.0_f32.sqrt();
|
||||
}
|
||||
}
|
||||
|
||||
fn canvas_frame_ui(&mut self, ui: &mut Ui) {
|
||||
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
||||
self.canvas_content_ui(ui);
|
||||
});
|
||||
}
|
||||
|
||||
fn canvas_content_ui(&self, ui: &mut Ui) {
|
||||
let Self {
|
||||
height,
|
||||
num_repeats,
|
||||
rel_freqs,
|
||||
} = self;
|
||||
|
||||
ui.style_mut().spacing.item_spacing = Vec2::ZERO;
|
||||
|
||||
let w = ui.available_width();
|
||||
|
||||
let fundamental_wavelength = w / (*num_repeats as f32);
|
||||
let fundamental_freq = 1.0 / fundamental_wavelength;
|
||||
|
||||
let mut shapes = vec![];
|
||||
|
||||
for overtone in 1.. {
|
||||
let h = *height / overtone as f32;
|
||||
if h <= 1.5 {
|
||||
break;
|
||||
}
|
||||
for (tone_nr, rel_freq) in rel_freqs.iter().enumerate() {
|
||||
let freq = fundamental_freq * rel_freq * (overtone as f32);
|
||||
let wavelen = 1.0 / freq;
|
||||
let stroke_width = h.sqrt();
|
||||
|
||||
// let h = wavelen / 4.0;
|
||||
|
||||
if wavelen <= 1.5 {
|
||||
break;
|
||||
}
|
||||
|
||||
let (rect, response) = ui.allocate_exact_size(vec2(w, h), Sense::hover());
|
||||
response.on_hover_text(format!("Tone {} * overtone {}", tone_nr, overtone));
|
||||
|
||||
for i in 0.. {
|
||||
let x = rect.left() + wavelen * (i as f32);
|
||||
if x > rect.right() + 0.5 {
|
||||
break;
|
||||
}
|
||||
|
||||
let stroke = Stroke::new(stroke_width, Color32::from_additive_luminance(150));
|
||||
shapes.push(Shape::line_segment(
|
||||
[pos2(x, rect.top()), pos2(x, rect.bottom())],
|
||||
stroke,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
ui.painter().extend(shapes);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue