feat(matrix): evolve edit/save/load + OSC routes
This commit is contained in:
@@ -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.()
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user