Replace nav buttons with a virtual joystick pad

This commit is contained in:
Armin 2026-10-09 17:58:07 +02:00
commit c7ebd3ed4d
6 changed files with 418 additions and 76 deletions

View file

@ -15,7 +15,7 @@ SM26AudioProcessorEditor::SM26AudioProcessorEditor (SM26AudioProcessor& p)
setResizeLimits (760, 620, 1500, 1300);
addAndMakeVisible (lcd);
lcd.onPressed = [this](int) { if (! menu.isOpen()) openPresetMenu(); };
lcd.onPressed = [](int) {};
setupKnobs();
setupNavButtons();
@ -69,38 +69,31 @@ void SM26AudioProcessorEditor::setupKnobs()
}
}
juce::Font SM26AudioProcessorEditor::NavButtonLookAndFeel::getTextButtonFont (juce::TextButton&, int)
{
return juce::Font (juce::FontOptions { juce::Font::getDefaultMonospacedFontName(),
10.5f, juce::Font::bold });
}
void SM26AudioProcessorEditor::setupNavButtons()
{
auto setup = [this](juce::TextButton& btn, juce::Colour bg)
{
btn.setLookAndFeel (&navLookAndFeel);
btn.setColour (juce::TextButton::buttonColourId, bg);
btn.setColour (juce::TextButton::textColourOffId, juce::Colour (0xFFE0E0E0));
btn.setColour (juce::ComboBox::outlineColourId, juce::Colour (0xFF444444));
addAndMakeVisible (btn);
addAndMakeVisible (navEnter);
addAndMakeVisible (navEsc);
addAndMakeVisible (navStick);
navStick.setRepeatSpeed (250, 50);
navStick.onAction = [this](int dir) {
switch (dir)
{
case JoystickPad::Up:
if (menu.isOpen()) menu.up();
else cyclePreset (-1);
break;
case JoystickPad::Down:
if (menu.isOpen()) menu.down();
else cyclePreset (+1);
break;
case JoystickPad::Left: menu.left(); break;
case JoystickPad::Right: menu.right(); break;
default: break;
}
};
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);
navDown.setTriggeredOnMouseDown (true);
navDown.setRepeatSpeed (250, 50);
navUp.onClick = [this] { if (menu.isOpen()) menu.up(); else cyclePreset (-1); };
navDown.onClick = [this] { if (menu.isOpen()) menu.down(); else cyclePreset (+1); };
navLeft.onClick = [this] { menu.left(); };
navRight.onClick = [this] { menu.right(); };
navEnter.onClick = [this] { if (menu.isOpen()) menu.enter(); else menu.open(); };
navEsc.onClick = [this] { if (menu.isOpen()) menu.escape(); else menu.close(); };
}
@ -332,45 +325,45 @@ void SM26AudioProcessorEditor::resized()
{
const float totalW = (float) getWidth();
const float totalH = (float) getHeight();
const float footerTop = totalH - 22.0f;
float knobSize = 78.0f;
float knobGap = 20.0f;
float knobsW = 4.0f * knobSize + 3.0f * knobGap;
float knobsX = (totalW - knobsW) / 2.0f;
float knobsY = juce::jmax (360.0f, totalH - 300.0f);
// ---- LCD -----------------------------------------------------------
lcd.setBounds (14, 16, (int) totalW - 28, 302);
const float lcdBottom = 16.0f + 302.0f;
// ---- navigation joystick: directly under the LCD --------------------
const float navSize = 30.0f;
const float navGap = 3.0f;
const float navCenterX = totalW / 2.0f;
const float navTop = lcdBottom + 12.0f;
const float stickS = juce::jlimit (64.0f, 116.0f, juce::jmin (116.0f, totalW * 0.35f));
const float stickLeft = navCenterX - stickS * 0.5f;
navStick.setBounds ((int) stickLeft, (int) navTop, (int) stickS, (int) stickS);
navEnter.setBounds ((int) (stickLeft - navSize - navGap),
(int) (navTop + stickS * 0.5f - navSize * 0.5f),
(int) navSize, (int) navSize);
navEsc.setBounds ((int) (stickLeft + stickS + navGap),
(int) (navTop + stickS * 0.5f - navSize * 0.5f),
(int) navSize, (int) navSize);
// ---- knobs: below the navigation -----------------------------------
const float knobSize = 62.0f;
const float knobGap = 14.0f;
const float knobsW = 4.0f * knobSize + 3.0f * knobGap;
const float knobsX = (totalW - knobsW) / 2.0f;
float knobsY = navTop + stickS + 26.0f;
knobsY = juce::jmin (knobsY, footerTop - (knobSize + 31.0f) - 10.0f);
for (int i = 0; i < 4; ++i)
{
float x = knobsX + (float) i * (knobSize + knobGap);
knobSliders[i].setBounds ((int) x, (int) knobsY, (int) knobSize, (int) knobSize);
knobLabels[i].setBounds ((int) x, (int) (knobsY + knobSize + 2), (int) knobSize, 18);
knobValueLabels[i].setBounds ((int) x, (int) (knobsY + knobSize + 20), (int) knobSize, 16);
knobLabels[i].setBounds ((int) x, (int) (knobsY + knobSize + 2), (int) knobSize, 14);
knobValueLabels[i].setBounds ((int) x, (int) (knobsY + knobSize + 16), (int) knobSize, 15);
}
float navSize = 30.0f;
float navGap = 3.0f;
float navCenterX = totalW / 2.0f;
float legendBottom = knobsY + knobSize + 20.0f + 16.0f;
float footerTop = totalH - 22.0f;
float navCenterY = (legendBottom + footerTop) * 0.5f;
navUp.setBounds ((int) (navCenterX - navSize / 2), (int) (navCenterY - navSize - navGap),
(int) navSize, (int) navSize);
navDown.setBounds ((int) (navCenterX - navSize / 2), (int) (navCenterY + navGap),
(int) navSize, (int) navSize);
navLeft.setBounds ((int) (navCenterX - navSize - navGap - navSize / 2), (int) (navCenterY - navSize / 2),
(int) navSize, (int) navSize);
navRight.setBounds ((int) (navCenterX + navGap + navSize / 2), (int) (navCenterY - navSize / 2),
(int) navSize, (int) navSize);
navEnter.setBounds ((int) (navCenterX - navSize - navGap), (int) (navCenterY + navSize + navGap),
(int) navSize, (int) navSize);
navEsc.setBounds ((int) (navCenterX + navGap), (int) (navCenterY + navSize + navGap),
(int) navSize, (int) navSize);
lcd.setBounds (14, 16, (int) totalW - 28, 302);
footer.setBounds (8, (int) totalH - 22, (int) totalW - 16, 16);
footer.setBounds (8, (int) footerTop, (int) totalW - 16, 16);
}
void SM26AudioProcessorEditor::timerCallback()