feat(matrix): evolve edit/save/load + OSC routes

This commit is contained in:
L'électron rare
2026-06-29 20:31:32 +02:00
parent b254d7cf1d
commit 47fe6a46af
2 changed files with 36 additions and 1 deletions
+14 -1
View File
@@ -438,6 +438,7 @@ File.exists(~matDir).not.if({ ("mkdir -p " ++ ~matDir.quote).systemCmd });
~matSetCell = { |vi, bar, color|
(vi >= 0 and: { vi < ~matVoices.size and: { bar >= 0 and: { bar < ~matBars } } }).if({
~lp[\matrix][vi][bar] = color.clip(0, 6).asInteger;
(~matEvolve and: { ~matBaseGrid.notNil }).if({ ~matBaseGrid[vi][bar] = ~lp[\matrix][vi][bar] });
(~lp[\matPlaying] and: { bar == ~lp[\matBar] }).if({ ~matApplyBar.(bar) });
~toscSend !? { ~toscSend.("/matrix/cell", vi, bar, ~lp[\matrix][vi][bar]) }
})
@@ -640,7 +641,7 @@ OSCdef(\mat_steps_get, { |msg, time, addr|
var safe = ~matSafeName.(name);
var path = ~matDir +/+ (safe ++ ".matrix");
var payload = (
grid: ~lp[\matrix],
grid: (~matEvolve.if({ ~matBaseGrid ? ~lp[\matrix] }, { ~lp[\matrix] })),
instruments: ~matInstruments.collect({ |x| (x ? \default) }),
colorDefs: ~matColorDefs.collect({ |defs| (1..6).collect({ |c| defs[c] }) }),
voiceMods: ~matVoices.collect({ |name| ~matVoiceMods[name] ? [] }),
@@ -664,6 +665,7 @@ OSCdef(\mat_steps_get, { |msg, time, addr|
grid = grid.isArray.if({ ~matMigrateGrid.(grid) }, { grid }); // pad/tile to current dims
~matGridValid.(grid).if({
~lp[\matrix] = grid;
(~matEvolve).if({ ~matBaseGrid = ~lp[\matrix].collect({ |row| row.copy }) });
// restore instruments (default nil; validate against choices)
~matVoices.do { |name, vi|
var sym = (insts.notNil).if({ insts[vi] }, { \default });
@@ -916,6 +918,17 @@ OSCdef(\mat_play, { |msg, time, addr|
~matPlay.()
}, '/matrix/play');
OSCdef(\mat_evolve, { |msg, time, addr|
~toscTouch !? { ~toscTouch.(addr) };
~matSetEvolve.((msg[1] ? 0).asInteger > 0)
}, '/matrix/evolve');
OSCdef(\mat_evolverate, { |msg, time, addr|
~toscTouch !? { ~toscTouch.(addr) };
~matEvolveRate = (msg[1] ? 0.15).asFloat.clip(0, 1);
~matEvolvePush.()
}, '/matrix/evolverate');
OSCdef(\mat_stop, { |msg, time, addr|
~toscTouch !? { ~toscTouch.(addr) };
~matStop.()
+22
View File
@@ -848,6 +848,28 @@ pass = pass and: { ~matBaseGrid == ~evSnap }; // base unchanged by steps
~matSetEvolve.(false); // restore
pass = pass and: { ~lp[\matrix] == ~evSnap }; // working grid back to base
// -- Task 2: persistence integration + OSC routes --
// edit during evolve writes through to the base (survives next cycle)
~lp[\matrix] = Array.fill(~matVoices.size, { Array.fill(~matBars, 0) });
~lp[\matrix][0][0] = 1;
~matSetEvolve.(true); // base = current grid
~matSetCell.(0, 0, 4); // edit while evolving
pass = pass and: { ~matBaseGrid[0][0] == 4 }; // base updated, not just working grid
// save serializes the base, not the mutated working grid
~matEvolveRate = 1.0; ~matEvolveStep.(); // working grid now mutated
~matSave.("ev_tmp");
~evRaw = File.use(~matDir +/+ "ev_tmp.matrix", "r", { |f| f.readAllString }).interpret;
pass = pass and: { ~evRaw[\grid][0][0] == 4 }; // saved = base value, not the mutated one
File.delete(~matDir +/+ "ev_tmp.matrix");
~matSetEvolve.(false);
// OSCdefs route through to the setters
OSCdef(\mat_evolverate).func.value(['/matrix/evolverate', 0.42]);
pass = pass and: { (~matEvolveRate - 0.42).abs < 0.001 };
OSCdef(\mat_evolve).func.value(['/matrix/evolve', 1]);
pass = pass and: { ~matEvolve == true and: { ~matBaseGrid.notNil } };
OSCdef(\mat_evolve).func.value(['/matrix/evolve', 0]);
pass = pass and: { ~matEvolve == false };
pass.if(
{ "TEST PASS".postln },
{ "TEST FAIL".postln }