diff --git a/sound_algo/data_only/matrix.scd b/sound_algo/data_only/matrix.scd index 2bab630..beef03c 100644 --- a/sound_algo/data_only/matrix.scd +++ b/sound_algo/data_only/matrix.scd @@ -407,10 +407,15 @@ File.exists(~matDir).not.if({ ("mkdir -p " ++ ~matDir.quote).systemCmd }); }); }; -// one mutation from a base snapshot + re-source (the evolve one-shot) +// one mutation + re-source (the evolve one-shot). When the evolve toggle is +// OFF, snapshot/mutate/discard so ~matBaseGrid (owned by the toggle: non-nil +// iff evolve active) is never leaked across a preset load. When ON, keep the +// persistent base and just re-mutate from it. ~matRelanceEvolve = { - ~matBaseGrid.isNil.if({ ~matBaseGrid = ~lp[\matrix].collect({ |row| row.copy }) }); + var hadBase = ~matBaseGrid.notNil; + hadBase.not.if({ ~matBaseGrid = ~lp[\matrix].collect({ |row| row.copy }) }); ~matEvolveStep.(); + hadBase.not.if({ ~matBaseGrid = nil }); ~matVoices.size.do { |i| ~matLastColor[i] = -1 }; (~lp[\matPlaying] == true).if({ ~matApplyBar.(~lp[\matBar] ? 0) }); }; diff --git a/sound_algo/data_only/matrix_presets/test_global_actions.scd b/sound_algo/data_only/matrix_presets/test_global_actions.scd index 6d1278c..193d816 100644 --- a/sound_algo/data_only/matrix_presets/test_global_actions.scd +++ b/sound_algo/data_only/matrix_presets/test_global_actions.scd @@ -67,6 +67,19 @@ feat.load; (~matGlobalActions == [\evolve, \breakdown, \fill, \drop]).not.if({ pass = false; "FAIL: globalActions not round-tripped".postln }); ("rm -f '" ++ (~matDir +/+ "zz_gact_test.matrix") ++ "'").systemCmd; +// -- I: evolve one-shot must not leak ~matBaseGrid when the toggle is off, +// and must mutate from the CURRENT grid (not a stale snapshot) -- +~matEvolve = false; ~matBaseGrid = nil; +~lp[\matrix] = Array.fill(~matVoices.size, { Array.fill(~matBars, 0) }); +~lp[\matrix][0][0] = 3; // gridA: kick bar0 active +~matRelanceEvolve.(); +(~matBaseGrid.isNil).not.if({ pass = false; "FAIL: evolve one-shot leaked baseGrid".postln }); +~lp[\matrix] = Array.fill(~matVoices.size, { Array.fill(~matBars, 0) }); +~lp[\matrix][1][5] = 2; // gridB: hats bar5 active +~matRelanceEvolve.(); +(~lp[\matrix][0][0] == 0).not.if({ pass = false; "FAIL: stale gridA cell resurrected by evolve".postln }); +(~lp[\matrix][1][5] > 0).not.if({ pass = false; "FAIL: gridB active cell lost by evolve".postln }); + pass.if({ "GLOBALACT PASS".postln }, { "GLOBALACT FAIL".postln }); 0.exit; )