Feat: introduce follow up actions
Some checks failed
Deploy Website / deploy (push) Failing after 4m49s

This commit is contained in:
2026-02-22 03:59:09 +01:00
parent 003ee0518e
commit 8ba98e8f3b
25 changed files with 203 additions and 307 deletions

View File

@@ -94,7 +94,6 @@ pub enum Op {
Triangle,
Range,
Perlin,
Chain,
Loop,
Degree(&'static [i64]),
Oct,

View File

@@ -59,7 +59,6 @@ pub struct StepContext<'a> {
pub nudge_secs: f64,
pub cc_access: Option<&'a dyn CcAccess>,
pub speed_key: &'a str,
pub chain_key: &'a str,
pub mouse_x: f64,
pub mouse_y: f64,
pub mouse_down: f64,

View File

@@ -992,26 +992,6 @@ impl Forth {
.insert(ctx.speed_key.to_string(), Value::Float(clamped, None));
}
Op::Chain => {
let pattern = pop_int(stack)? - 1;
let bank = pop_int(stack)? - 1;
if bank < 0 || pattern < 0 {
return Err("chain: bank and pattern must be >= 1".into());
}
if bank as usize == ctx.bank && pattern as usize == ctx.pattern {
// chaining to self is a no-op
} else {
use std::fmt::Write;
let mut val = String::with_capacity(8);
let _ = write!(&mut val, "{bank}:{pattern}");
var_writes_cell
.borrow_mut()
.as_mut()
.expect("var_writes taken")
.insert(ctx.chain_key.to_string(), Value::Str(Arc::from(val), None));
}
}
Op::Loop => {
let beats = pop_float(stack)?;
if ctx.tempo == 0.0 || ctx.speed == 0.0 {

View File

@@ -89,7 +89,6 @@ pub(super) fn simple_op(name: &str) -> Option<Op> {
"triangle" => Op::Triangle,
"range" => Op::Range,
"perlin" => Op::Perlin,
"chain" => Op::Chain,
"loop" => Op::Loop,
"oct" => Op::Oct,
"clear" => Op::ClearCmd,

View File

@@ -254,16 +254,6 @@ pub(super) const WORDS: &[Word] = &[
compile: Simple,
varargs: false,
},
Word {
name: "chain",
aliases: &[],
category: "Time",
stack: "(bank pattern --)",
desc: "Chain to bank/pattern (1-indexed) when current pattern ends",
example: "1 4 chain",
compile: Simple,
varargs: false,
},
Word {
name: "at",
aliases: &[],

View File

@@ -7,4 +7,4 @@ pub const MAX_STEPS: usize = 1024;
pub const DEFAULT_LENGTH: usize = 16;
pub use file::{load, save, FileError};
pub use project::{Bank, LaunchQuantization, Pattern, PatternSpeed, Project, Step, SyncMode};
pub use project::{Bank, FollowUp, LaunchQuantization, Pattern, PatternSpeed, Project, Step, SyncMode};

View File

@@ -206,6 +206,44 @@ impl SyncMode {
}
}
#[derive(Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
pub enum FollowUp {
#[default]
Loop,
Stop,
Chain { bank: usize, pattern: usize },
}
impl FollowUp {
pub fn label(&self) -> &'static str {
match self {
Self::Loop => "Loop",
Self::Stop => "Stop",
Self::Chain { .. } => "Chain",
}
}
pub fn next_mode(&self) -> Self {
match self {
Self::Loop => Self::Stop,
Self::Stop => Self::Chain { bank: 0, pattern: 0 },
Self::Chain { .. } => Self::Loop,
}
}
pub fn prev_mode(&self) -> Self {
match self {
Self::Loop => Self::Chain { bank: 0, pattern: 0 },
Self::Stop => Self::Loop,
Self::Chain { .. } => Self::Stop,
}
}
}
fn is_default_follow_up(f: &FollowUp) -> bool {
*f == FollowUp::default()
}
#[derive(Clone, Serialize, Deserialize)]
pub struct Step {
pub active: bool,
@@ -245,6 +283,7 @@ pub struct Pattern {
pub name: Option<String>,
pub quantization: LaunchQuantization,
pub sync_mode: SyncMode,
pub follow_up: FollowUp,
}
#[derive(Serialize, Deserialize)]
@@ -280,6 +319,8 @@ struct SparsePattern {
quantization: LaunchQuantization,
#[serde(default, skip_serializing_if = "is_default_sync_mode")]
sync_mode: SyncMode,
#[serde(default, skip_serializing_if = "is_default_follow_up")]
follow_up: FollowUp,
}
fn is_default_quantization(q: &LaunchQuantization) -> bool {
@@ -302,6 +343,8 @@ struct LegacyPattern {
quantization: LaunchQuantization,
#[serde(default)]
sync_mode: SyncMode,
#[serde(default)]
follow_up: FollowUp,
}
impl Serialize for Pattern {
@@ -327,6 +370,7 @@ impl Serialize for Pattern {
name: self.name.clone(),
quantization: self.quantization,
sync_mode: self.sync_mode,
follow_up: self.follow_up,
};
sparse.serialize(serializer)
}
@@ -361,6 +405,7 @@ impl<'de> Deserialize<'de> for Pattern {
name: sparse.name,
quantization: sparse.quantization,
sync_mode: sparse.sync_mode,
follow_up: sparse.follow_up,
})
}
PatternFormat::Legacy(legacy) => Ok(Pattern {
@@ -370,6 +415,7 @@ impl<'de> Deserialize<'de> for Pattern {
name: legacy.name,
quantization: legacy.quantization,
sync_mode: legacy.sync_mode,
follow_up: legacy.follow_up,
}),
}
}
@@ -384,6 +430,7 @@ impl Default for Pattern {
name: None,
quantization: LaunchQuantization::default(),
sync_mode: SyncMode::default(),
follow_up: FollowUp::default(),
}
}
}