From 9c88380d1b4484dda3f943d89552b739396faa2d Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 13 Aug 2026 14:39:56 +0200 Subject: [PATCH] Fix preset name not restored on plugin reopen The plugin saved only parameter values, so on reopening the editor reset to the default "Zero State" even though another patch was selected. Store the chosen preset name as a presetName property on the APVTS ValueTree (set on preset select, randomize, and .cfl load) so it round-trips with the saved state and the editor restores the correct name and index. Parameter tweaks made after selecting a preset are preserved since only the label is restored, not re-applied. --- Source/PluginEditor.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index a6e85ea..7aa4480 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -749,8 +749,24 @@ MainContentComponent::MainContentComponent(ChromaFlockProcessor& p) auto& presets = processorRef.presetManager.getPresets(); if (!presets.empty()) { - currentPresetIndex = 0; - patchLCD.setText(presets[currentPresetIndex].name); + // Restore the preset name from the saved state so re-opening the + // plugin shows the patch the user last selected instead of defaulting + // to "Zero State". The parameter values themselves are already + // restored by the host via setStateInformation. + currentPresetIndex = -1; + auto savedName = processorRef.apvts.state.getProperty("presetName", juce::String()).toString(); + if (savedName.isNotEmpty()) { + for (size_t i = 0; i < presets.size(); ++i) { + if (presets[i].name == savedName) { + currentPresetIndex = static_cast(i); + break; + } + } + patchLCD.setText(savedName); + } else { + currentPresetIndex = 0; + patchLCD.setText(presets[currentPresetIndex].name); + } } scaleLabel.setText("SCALE", juce::dontSendNotification); @@ -1022,6 +1038,7 @@ void MainContentComponent::loadPresetFile() { currentPresetIndex = -1; patchLCD.setText(file.getFileNameWithoutExtension()); + processorRef.apvts.state.setProperty("presetName", file.getFileNameWithoutExtension(), nullptr); setupSyncKnob(lfo1RateKnob, lfo1RateAttach, lfo1BeatAttach, "lfo1Rate", "lfo1Beat", lfo1SyncLed.isLit()); setupSyncKnob(lfo2RateKnob, lfo2RateAttach, lfo2BeatAttach, "lfo2Rate", "lfo2Beat", lfo2SyncLed.isLit()); @@ -1036,6 +1053,7 @@ void MainContentComponent::applyCurrentPreset() { processorRef.fadeOutActiveVoices(0.25f); processorRef.presetManager.applyPreset(presets[currentPresetIndex].name, processorRef.apvts); patchLCD.setText(presets[currentPresetIndex].name); + processorRef.apvts.state.setProperty("presetName", presets[currentPresetIndex].name, nullptr); // The LedToggle updates itself via its timer, so re-sync the rate/beat // knob attachments to match. @@ -1062,6 +1080,7 @@ void MainContentComponent::randomizeParameters() { } patchLCD.setText("RANDOM"); + processorRef.apvts.state.setProperty("presetName", "RANDOM", nullptr); // Re-sync the rate/beat knob attachments to match the randomized sync states. setupSyncKnob(lfo1RateKnob, lfo1RateAttach, lfo1BeatAttach, "lfo1Rate", "lfo1Beat", lfo1SyncLed.isLit());