Persist engine state in DAW projects, black monochrome panel, expand preset bank

- Save/load the engine's full parameter set alongside the preset index so
  knob and menu tweaks survive relaunching a song project
- Make the plugin panel black: top/surround laser border and bottom deck
  (rotary + nav keys) are now #000000
- Extend factory bank to 320 categorized presets and add LCD click-to-open
  preset category browser
This commit is contained in:
Armin 2026-09-13 22:04:43 +02:00
commit bdd3b38cee
7 changed files with 943 additions and 56 deletions

View file

@ -71,26 +71,53 @@ juce::AudioProcessorEditor* SM26AudioProcessor::createEditor()
void SM26AudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
auto xmlStr = apvts.copyState().createXml()->toString();
auto state = apvts.copyState();
if (state.getChildWithName ("engine").isValid())
state.removeChild (state.getChildWithName ("engine"), nullptr);
juce::ValueTree engineState ("engine");
for (int i = 0; i < sm26::kNumParams; ++i)
engineState.setProperty (juce::Identifier (juce::String ("p") + juce::String (i)),
(double) engine.getParam (i), nullptr);
state.appendChild (engineState, nullptr);
auto xmlStr = state.createXml()->toString();
destData.replaceAll (xmlStr.toRawUTF8(), (size_t) xmlStr.length());
}
void SM26AudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
auto xml = juce::XmlDocument::parse (juce::String::fromUTF8 ((const char*) data, sizeInBytes));
if (xml != nullptr)
if (xml == nullptr)
return;
auto tree = juce::ValueTree::fromXml (*xml);
if (! tree.isValid())
return;
auto engineState = tree.getChildWithName ("engine");
paramsReady.store (false);
apvts.replaceState (tree);
paramsReady.store (true);
int idx = (int) *apvts.getRawParameterValue ("preset");
idx = juce::jlimit (0, sm26::PresetStore::count() - 1, idx);
engine.setPresetIndex (idx);
if (engineState.isValid())
{
auto tree = juce::ValueTree::fromXml (*xml);
if (tree.isValid())
for (int i = 0; i < sm26::kNumParams; ++i)
{
paramsReady.store (false);
apvts.replaceState (tree);
paramsReady.store (true);
int idx = (int) *apvts.getRawParameterValue ("preset");
engine.setPresetIndex (idx);
applyPresetKnobs();
auto prop = engineState.getProperty (juce::Identifier (juce::String ("p") + juce::String (i)));
if (prop.isVoid())
continue;
engine.setParam (i, (float) (double) prop);
}
}
applyPresetKnobs();
}
void SM26AudioProcessor::setKnob (int knob, float value01)