Euclidean + hue rotation

This commit is contained in:
2026-02-02 13:25:27 +01:00
parent 7348bd38b1
commit d54d9218c1
21 changed files with 1338 additions and 53 deletions

View File

@@ -111,6 +111,7 @@ impl App {
flash_brightness: self.ui.flash_brightness,
color_scheme: self.ui.color_scheme,
layout: self.audio.config.layout,
hue_rotation: self.ui.hue_rotation,
..Default::default()
},
link: crate::settings::LinkSettings {
@@ -1311,7 +1312,15 @@ impl App {
}
AppCommand::SetColorScheme(scheme) => {
self.ui.color_scheme = scheme;
crate::theme::set(scheme.to_theme());
let base_theme = scheme.to_theme();
let rotated = cagire_ratatui::theme::transform::rotate_theme(base_theme, self.ui.hue_rotation);
crate::theme::set(rotated);
}
AppCommand::SetHueRotation(degrees) => {
self.ui.hue_rotation = degrees;
let base_theme = self.ui.color_scheme.to_theme();
let rotated = cagire_ratatui::theme::transform::rotate_theme(base_theme, degrees);
crate::theme::set(rotated);
}
AppCommand::ToggleRuntimeHighlight => {
self.ui.runtime_highlight = !self.ui.runtime_highlight;
@@ -1429,6 +1438,65 @@ impl App {
AppCommand::ResetPeakVoices => {
self.metrics.peak_voices = 0;
}
// Euclidean distribution
AppCommand::ApplyEuclideanDistribution {
bank,
pattern,
source_step,
pulses,
steps,
rotation,
} => {
let pat_len = self.project_state.project.pattern_at(bank, pattern).length;
let rhythm = euclidean_rhythm(pulses, steps, rotation);
let mut created_count = 0;
for (i, &is_hit) in rhythm.iter().enumerate() {
if !is_hit {
continue;
}
let target = (source_step + i) % pat_len;
if target == source_step {
continue;
}
if let Some(step) = self
.project_state
.project
.pattern_at_mut(bank, pattern)
.step_mut(target)
{
step.source = Some(source_step);
step.script.clear();
step.command = None;
step.active = true;
}
created_count += 1;
}
self.project_state.mark_dirty(bank, pattern);
for (i, &is_hit) in rhythm.iter().enumerate() {
if !is_hit || i == 0 {
continue;
}
let target = (source_step + i) % pat_len;
let saved = self.editor_ctx.step;
self.editor_ctx.step = target;
self.compile_current_step(link);
self.editor_ctx.step = saved;
}
self.load_step_to_editor();
self.ui.flash(
&format!("Created {} linked steps (E({pulses},{steps}))", created_count),
200,
FlashKind::Success,
);
}
}
}
@@ -1481,3 +1549,21 @@ impl App {
}
}
}
fn euclidean_rhythm(pulses: usize, steps: usize, rotation: usize) -> Vec<bool> {
if pulses == 0 || steps == 0 || pulses > steps {
return vec![false; steps];
}
let mut pattern = vec![false; steps];
for i in 0..pulses {
let pos = (i * steps) / pulses;
pattern[pos] = true;
}
if rotation > 0 {
pattern.rotate_left(rotation % steps);
}
pattern
}