chain word and better save/load UI

This commit is contained in:
2026-01-23 23:36:23 +01:00
parent 42ad77d9ae
commit 3bb19cbda8
20 changed files with 775 additions and 132 deletions

View File

@@ -6,7 +6,7 @@ use std::time::Duration;
use super::LinkState;
use crate::model::{MAX_BANKS, MAX_PATTERNS};
use crate::model::{Dictionary, ExecutionTrace, Rng, ScriptEngine, StepContext, Variables};
use crate::model::{Dictionary, ExecutionTrace, Rng, ScriptEngine, StepContext, Value, Variables};
use crate::state::LiveKeyState;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@@ -367,10 +367,13 @@ fn sequencer_loop(
step_traces.retain(|&(bank, pattern, _), _| {
bank != id.bank || pattern != id.pattern
});
let chain_key = format!("__chain_{}_{}__", id.bank, id.pattern);
variables.lock().unwrap().remove(&chain_key);
}
}
let prev_beat = audio_state.prev_beat;
let mut chain_transitions: Vec<(PatternId, PatternId)> = Vec::new();
for (_id, active) in audio_state.active_patterns.iter_mut() {
let Some(pattern) = pattern_cache.get(active.bank, active.pattern) else {
@@ -397,6 +400,7 @@ fn sequencer_loop(
let ctx = StepContext {
step: step_idx,
beat,
bank: active.bank,
pattern: active.pattern,
tempo,
phase: beat % quantum,
@@ -440,11 +444,44 @@ fn sequencer_loop(
let next_step = active.step_index + 1;
if next_step >= pattern.length {
active.iter += 1;
let chain_key = format!("__chain_{}_{}__", active.bank, active.pattern);
let chain_target = {
let vars = variables.lock().unwrap();
vars.get(&chain_key).and_then(|v| {
if let Value::Str(s, _) = v {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() == 2 {
let b = parts[0].parse::<usize>().ok()?;
let p = parts[1].parse::<usize>().ok()?;
Some(PatternId { bank: b, pattern: p })
} else {
None
}
} else {
None
}
})
};
if let Some(target) = chain_target {
let source = PatternId { bank: active.bank, pattern: active.pattern };
chain_transitions.push((source, target));
}
}
active.step_index = next_step % pattern.length;
}
}
for (source, target) in chain_transitions {
if !audio_state.pending_stops.contains(&source) {
audio_state.pending_stops.push(source);
}
if !audio_state.pending_starts.contains(&target) {
audio_state.pending_starts.push(target);
}
let chain_key = format!("__chain_{}_{}__", source.bank, source.pattern);
variables.lock().unwrap().remove(&chain_key);
}
{
let mut state = shared_state.lock().unwrap();
state.active_patterns = audio_state