mirror of
https://codeberg.org/armin/sm-26.git
synced 2026-10-11 17:01:53 +02:00
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:
parent
78e8ee80ad
commit
bdd3b38cee
7 changed files with 943 additions and 56 deletions
|
|
@ -15,6 +15,7 @@ SM26AudioProcessorEditor::SM26AudioProcessorEditor (SM26AudioProcessor& p)
|
|||
setResizeLimits (760, 620, 1500, 1300);
|
||||
|
||||
addAndMakeVisible (lcd);
|
||||
lcd.onPressed = [this](int) { if (! menu.isOpen()) openPresetMenu(); };
|
||||
setupKnobs();
|
||||
setupNavButtons();
|
||||
|
||||
|
|
@ -85,12 +86,12 @@ void SM26AudioProcessorEditor::setupNavButtons()
|
|||
addAndMakeVisible (btn);
|
||||
};
|
||||
|
||||
setup (navUp, juce::Colour (0xFF2A2A2A));
|
||||
setup (navDown, juce::Colour (0xFF2A2A2A));
|
||||
setup (navLeft, juce::Colour (0xFF2A2A2A));
|
||||
setup (navRight, juce::Colour (0xFF2A2A2A));
|
||||
setup (navEnter, juce::Colour (0xFF3F3F3F));
|
||||
setup (navEsc, juce::Colour (0xFF333333));
|
||||
setup (navUp, juce::Colour (0xFF000000));
|
||||
setup (navDown, juce::Colour (0xFF000000));
|
||||
setup (navLeft, juce::Colour (0xFF000000));
|
||||
setup (navRight, juce::Colour (0xFF000000));
|
||||
setup (navEnter, juce::Colour (0xFF000000));
|
||||
setup (navEsc, juce::Colour (0xFF000000));
|
||||
|
||||
navUp.setTriggeredOnMouseDown (true);
|
||||
navUp.setRepeatSpeed (250, 50);
|
||||
|
|
@ -120,17 +121,6 @@ void SM26AudioProcessorEditor::buildRootMenu()
|
|||
s.title = "SM-26 MAIN MENU";
|
||||
s.selected = 0;
|
||||
|
||||
auto addPreset = [&](const char* name, int idx) -> MenuItem
|
||||
{
|
||||
MenuItem item;
|
||||
item.label = name;
|
||||
item.kind = MenuItem::Action;
|
||||
item.onEnter = [this, idx]() {
|
||||
proc.setPresetByIndex (idx);
|
||||
};
|
||||
return item;
|
||||
};
|
||||
|
||||
auto addValue = [&](const char* n, int pid) -> MenuItem
|
||||
{
|
||||
MenuItem mi;
|
||||
|
|
@ -167,27 +157,7 @@ void SM26AudioProcessorEditor::buildRootMenu()
|
|||
MenuItem m;
|
||||
m.label = "PRESETS (" + juce::String (sm26::PresetStore::count()) + ")";
|
||||
m.kind = MenuItem::Submenu;
|
||||
m.onEnter = [this, addPreset]() {
|
||||
MenuScreen ps;
|
||||
ps.title = "SELECT PRESET";
|
||||
ps.selected = proc.engine.presetIndex();
|
||||
juce::String lastCat;
|
||||
const int count = sm26::PresetStore::count();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const auto* p = sm26::PresetStore::get (i);
|
||||
if (lastCat != p->category)
|
||||
{
|
||||
MenuItem h;
|
||||
h.label = "---- " + juce::String (p->category) + " ----";
|
||||
h.kind = MenuItem::Separator;
|
||||
ps.items.push_back (h);
|
||||
lastCat = p->category;
|
||||
}
|
||||
ps.items.push_back (addPreset (p->name, i));
|
||||
}
|
||||
menu.pushScreen (ps);
|
||||
};
|
||||
m.onEnter = [this]() { openPresetMenu(); };
|
||||
s.items.push_back (m);
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +247,64 @@ void SM26AudioProcessorEditor::buildRootMenu()
|
|||
menu.setRootScreenBuilder (builder);
|
||||
}
|
||||
|
||||
void SM26AudioProcessorEditor::openPresetMenu()
|
||||
{
|
||||
struct Cat { juce::String name; int first; int count; };
|
||||
std::vector<Cat> cats;
|
||||
const int total = sm26::PresetStore::count();
|
||||
for (int i = 0; i < total; ++i)
|
||||
{
|
||||
const auto* p = sm26::PresetStore::get (i);
|
||||
if (cats.empty() || cats.back().name != p->category)
|
||||
cats.push_back ({ juce::String (p->category), i, 0 });
|
||||
cats.back().count++;
|
||||
}
|
||||
|
||||
MenuScreen s;
|
||||
s.title = "SELECT PATCH CATEGORY";
|
||||
s.selected = 0;
|
||||
|
||||
const juce::String curCat = sm26::PresetStore::findByIndex (proc.engine.presetIndex())->category;
|
||||
for (int c = 0; c < (int) cats.size(); ++c)
|
||||
{
|
||||
if (cats[(size_t) c].name == curCat)
|
||||
s.selected = c;
|
||||
|
||||
MenuItem mi;
|
||||
mi.label = cats[(size_t) c].name + " (" + juce::String (cats[(size_t) c].count) + ")";
|
||||
mi.kind = MenuItem::Submenu;
|
||||
mi.onEnter = [this, cats, c]() {
|
||||
const Cat& cat = cats[(size_t) c];
|
||||
MenuScreen catScreen;
|
||||
catScreen.title = "PATCHES: " + cat.name;
|
||||
catScreen.selected = 0;
|
||||
|
||||
const juce::String curName = sm26::PresetStore::findByIndex (proc.engine.presetIndex())->name;
|
||||
for (int i = cat.first; i < cat.first + cat.count; ++i)
|
||||
{
|
||||
const auto* p = sm26::PresetStore::get (i);
|
||||
if (juce::String (p->name) == curName)
|
||||
catScreen.selected = i - cat.first;
|
||||
|
||||
MenuItem pi;
|
||||
pi.label = p->name;
|
||||
pi.kind = MenuItem::Action;
|
||||
pi.onEnter = [this, i]() {
|
||||
proc.setPresetByIndex (i);
|
||||
menu.close();
|
||||
};
|
||||
catScreen.items.push_back (pi);
|
||||
}
|
||||
menu.pushScreen (catScreen);
|
||||
};
|
||||
s.items.push_back (mi);
|
||||
}
|
||||
|
||||
if (! menu.isOpen())
|
||||
menu.open();
|
||||
menu.pushScreen (s);
|
||||
}
|
||||
|
||||
void SM26AudioProcessorEditor::paint (juce::Graphics& g)
|
||||
{
|
||||
g.fillAll (juce::Colour (0xFF000000));
|
||||
|
|
@ -284,12 +312,17 @@ void SM26AudioProcessorEditor::paint (juce::Graphics& g)
|
|||
const float totalW = (float) getWidth();
|
||||
const float totalH = (float) getHeight();
|
||||
|
||||
g.setColour (juce::Colour (0xFF1A1A1A));
|
||||
g.setColour (juce::Colour (0xFF000000));
|
||||
g.fillRoundedRectangle (8.0f, 8.0f, totalW - 16.0f, totalH - 16.0f, 6.0f);
|
||||
|
||||
g.setColour (juce::Colour (0xFF333333));
|
||||
g.setColour (juce::Colour (0xFF000000));
|
||||
g.drawRoundedRectangle (8.0f, 8.0f, totalW - 16.0f, totalH - 16.0f, 6.0f, 1.5f);
|
||||
|
||||
const float lcdBottom = 16.0f + 302.0f;
|
||||
g.setColour (juce::Colour (0xFF000000));
|
||||
g.fillRoundedRectangle (8.0f, lcdBottom, totalW - 16.0f,
|
||||
juce::jmax (0.0f, totalH - 16.0f - lcdBottom), 6.0f);
|
||||
|
||||
g.setColour (juce::Colour (0xFFC8C8C8));
|
||||
g.setFont (juce::Font (juce::FontOptions { juce::Font::getDefaultMonospacedFontName(), 14.0f, juce::Font::bold }));
|
||||
g.drawText ("SM-26", 20.0f, 16.0f, 100.0f, 22.0f, juce::Justification::centredLeft);
|
||||
|
|
@ -417,7 +450,7 @@ void SM26AudioProcessorEditor::updateLCD()
|
|||
juce::String notesStr = notes > 0 ? "NOTES:" + juce::String (notes) : "";
|
||||
|
||||
lcd.setLine (6, bpmStr + (notesStr.isNotEmpty() ? " " + notesStr : ""));
|
||||
lcd.setLine (7, juce::String ("SM-26") + " UP/DN=PATCH OK=MENU");
|
||||
lcd.setLine (7, juce::String ("SM-26") + " UP/DN=PATCH CLICK=BROWSE OK=MENU");
|
||||
for (int r = 0; r < LcdDisplay::kRows; ++r)
|
||||
lcd.setInverted (r, false);
|
||||
lcd.showCursor (false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue