Skip to content

Commit 7ff5061

Browse files
author
tlr
committed
refactor top bar items into settings menu, add option to toggle repeated notes behavior
1 parent 06ae8dc commit 7ff5061

3 files changed

Lines changed: 87 additions & 53 deletions

File tree

src/PluginEditor.cpp

Lines changed: 81 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ RipplerXAudioProcessorEditor::RipplerXAudioProcessorEditor (RipplerXAudioProcess
6262
sunImage, 1.0f, juce::Colours::transparentBlack,
6363
sunImage, 1.0f, juce::Colours::transparentBlack);
6464
}
65-
sun.setBounds(col+138, row+3, 20, 20);
65+
sun.setBounds(col+128, row+3, 20, 20);
6666
sun.onClick = [this] {
6767
audioProcessor.toggleTheme();
6868
loadTheme();
@@ -80,39 +80,14 @@ RipplerXAudioProcessorEditor::RipplerXAudioProcessorEditor (RipplerXAudioProcess
8080
moonImage, 1.0f, juce::Colours::transparentBlack,
8181
moonImage, 1.0f, juce::Colours::transparentBlack);
8282
}
83-
moon.setBounds(col+138, row+3, 20, 20);
83+
moon.setBounds(col+128, row+3, 20, 20);
8484
moon.onClick = [this] {
8585
audioProcessor.toggleTheme();
8686
loadTheme();
8787
repaint();
8888
};
8989

90-
col += 160;
91-
addAndMakeVisible(sizeLabel);
92-
sizeLabel.setColour(juce::Label::ColourIds::textColourId, Colour(globals::COLOR_NEUTRAL_LIGHT));
93-
sizeLabel.setFont(FontOptions(16.0f));
94-
sizeLabel.setText("UI", NotificationType::dontSendNotification);
95-
sizeLabel.setBounds(col, row, 30, 25);
96-
97-
addAndMakeVisible(sizeMenu);
98-
sizeMenu.addItem("100%", 1);
99-
sizeMenu.addItem("125%", 2);
100-
sizeMenu.addItem("150%", 3);
101-
sizeMenu.addItem("175%", 4);
102-
sizeMenu.addItem("200%", 5);
103-
sizeMenu.setSelectedId(audioProcessor.scale == 1.0f ? 1
104-
: audioProcessor.scale == 1.25f ? 2
105-
: audioProcessor.scale == 1.5f ? 3
106-
: audioProcessor.scale == 1.75f ? 4
107-
: 5);
108-
sizeMenu.onChange = [this]()
109-
{
110-
const int value = sizeMenu.getSelectedId();
111-
auto scale = value == 1 ? 1.0f : value == 2 ? 1.25f : value == 3 ? 1.5f : value == 4 ? 1.75f : 2.0f;
112-
audioProcessor.setScale(scale);
113-
setScaleFactor(audioProcessor.scale);
114-
};
115-
sizeMenu.setBounds(col+25,row,80,25);
90+
col += 215;
11691

11792
addAndMakeVisible(velButton);
11893
velButton.setTooltip("Toggle velocity mapping, can also be set by holding Shift+Drag on knobs");
@@ -127,13 +102,13 @@ RipplerXAudioProcessorEditor::RipplerXAudioProcessorEditor (RipplerXAudioProcess
127102
repaintVelSliders();
128103
};
129104
velButton.setButtonText("Vel Map");
130-
velButton.setBounds(col+115, row, 80, 25);
105+
velButton.setBounds(col, row, 80, 25);
131106

132107
addAndMakeVisible(polyLabel);
133108
polyLabel.setColour(juce::Label::ColourIds::textColourId, Colour(globals::COLOR_NEUTRAL_LIGHT));
134109
polyLabel.setFont(FontOptions(16.0f));
135110
polyLabel.setText("Voices", NotificationType::dontSendNotification);
136-
polyLabel.setBounds(col+115+80+5, row, 50, 25);
111+
polyLabel.setBounds(col+80+5, row, 50, 25);
137112

138113
addAndMakeVisible(polyMenu);
139114
polyMenu.addItem("1", 1);
@@ -150,18 +125,7 @@ RipplerXAudioProcessorEditor::RipplerXAudioProcessorEditor (RipplerXAudioProcess
150125
audioProcessor.setPolyphony(poly);
151126
});
152127
};
153-
polyMenu.setBounds(col+115+80+50+5,row,55,25);
154-
155-
addAndMakeVisible(stereoizerBtn);
156-
stereoizerBtn.setBounds(Rectangle<int>(50, 25).withPosition(polyMenu.getBounds().getTopRight().translated(6, 0)));
157-
stereoizerBtn.setAlpha(0.0f);
158-
stereoizerBtn.setTooltip("Toggle stereoizer FX");
159-
stereoizerBtn.onClick = [this]()
160-
{
161-
bool stereo = (bool)audioProcessor.params.getRawParameterValue("stereoizer")->load();
162-
audioProcessor.params.getParameter("stereoizer")->setValueNotifyingHost(stereo ? 0.0f : 1.0f);
163-
repaint();
164-
};
128+
polyMenu.setBounds(col+80+50+5,row,55,25);
165129

166130
addAndMakeVisible(presetMenu);
167131
presetMenu.setText("Patch");
@@ -256,6 +220,11 @@ RipplerXAudioProcessorEditor::RipplerXAudioProcessorEditor (RipplerXAudioProcess
256220
};
257221
presetMenu.setBounds(getWidth() - 110, row, 100, 25);
258222

223+
addAndMakeVisible(settingsBtn);
224+
settingsBtn.setBounds(Rectangle<int>(25, 25).withPosition(presetMenu.getBounds().getTopLeft().translated(-25 - 10+3, 0)));
225+
settingsBtn.setAlpha(0.f);
226+
settingsBtn.onClick = [this]() { showSettingsMenu(); };
227+
259228
// NOISE SLIDERS
260229
col = 10; row += 35;
261230

@@ -869,7 +838,6 @@ void RipplerXAudioProcessorEditor::loadTheme()
869838
malletLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
870839
malletSubLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
871840
envelopeLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
872-
sizeLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
873841
pitchLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL));
874842
polyLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
875843
aLabel.setColour(juce::Label::ColourIds::textColourId, Colour(COLOR_NEUTRAL_LIGHT));
@@ -910,12 +878,31 @@ void RipplerXAudioProcessorEditor::paint (Graphics& g)
910878
path.lineTo((float)bounds.getRight() - 3.0f, (float)bounds.getCentreY() - 2.0f);
911879
g.strokePath(path, PathStrokeType(2.0f));
912880

913-
// draw stereoizer button
914-
bounds = stereoizerBtn.getBounds();
915-
bool stereo = audioProcessor.params.getRawParameterValue("stereoizer")->load();
916-
g.setColour(Colour(stereo ? COLOR_ACTIVE : COLOR_NEUTRAL_LIGHT));
917-
g.setFont(14.f);
918-
g.drawText(stereo ? "Stereo" : "Mono", bounds, Justification::centred, false);
881+
// draw settings button
882+
drawGear(g, settingsBtn.getBounds(), 10, 6, Colour(COLOR_ACTIVE), Colour(COLOR_BACKGROUND));
883+
}
884+
885+
void RipplerXAudioProcessorEditor::drawGear(Graphics& g, Rectangle<int> bounds, float radius, int segs, Colour color, Colour background)
886+
{
887+
float x = bounds.toFloat().getCentreX();
888+
float y = bounds.toFloat().getCentreY();
889+
float oradius = radius;
890+
float iradius = radius / 3.f;
891+
float cradius = iradius / 1.5f;
892+
float coffset = MathConstants<float>::twoPi;
893+
float inc = MathConstants<float>::twoPi / segs;
894+
895+
g.setColour(color);
896+
g.fillEllipse(x - oradius, y - oradius, oradius * 2.f, oradius * 2.f);
897+
898+
g.setColour(background);
899+
for (int i = 0; i < segs; i++) {
900+
float angle = coffset + i * inc;
901+
float cx = x + std::cos(angle) * oradius;
902+
float cy = y + std::sin(angle) * oradius;
903+
g.fillEllipse(cx - cradius, cy - cradius, cradius * 2, cradius * 2);
904+
}
905+
g.fillEllipse(x - iradius, y - iradius, iradius * 2.f, iradius * 2.f);
919906
}
920907

921908
void RipplerXAudioProcessorEditor::repaintVelSliders()
@@ -947,6 +934,51 @@ void RipplerXAudioProcessorEditor::resized()
947934
{
948935
}
949936

937+
void RipplerXAudioProcessorEditor::showSettingsMenu()
938+
{
939+
bool stereoizer = (bool)audioProcessor.params.getRawParameterValue("stereoizer")->load();
940+
bool reuseVoices = (bool)audioProcessor.params.getRawParameterValue("reuse_voices")->load();
941+
942+
PopupMenu menu;
943+
PopupMenu scaleMenu;
944+
scaleMenu.addItem(1, "100%", true, audioProcessor.scale == 1.0f);
945+
scaleMenu.addItem(2, "125%", true, audioProcessor.scale == 1.25f);
946+
scaleMenu.addItem(3, "150%", true, audioProcessor.scale == 1.5f);
947+
scaleMenu.addItem(4, "175%", true, audioProcessor.scale == 1.75f);
948+
scaleMenu.addItem(5, "200%", true, audioProcessor.scale == 2.0f);
949+
950+
PopupMenu polyphonyMenu;
951+
polyphonyMenu.addItem(10, "Reuse voices on repeated notes", true, reuseVoices);
952+
953+
menu.addSubMenu("UI Scale", scaleMenu);
954+
menu.addSubMenu("Polyphony", polyphonyMenu);
955+
menu.addItem(11, "Stereoizer", true, stereoizer);
956+
957+
auto menuPos = localPointToGlobal(settingsBtn.getBounds().getBottomRight());
958+
menu.showMenuAsync(PopupMenu::Options()
959+
.withTargetScreenArea({ menuPos.getX() - 125, menuPos.getY(), 1, 1 }),
960+
[this, stereoizer, reuseVoices](int result) {
961+
if (result == 0) return;
962+
if (result == 1) audioProcessor.setScale(1.f);
963+
if (result == 2) audioProcessor.setScale(1.25f);
964+
if (result == 3) audioProcessor.setScale(1.5f);
965+
if (result == 4) audioProcessor.setScale(1.75f);
966+
if (result == 5) audioProcessor.setScale(2.f);
967+
if (result >= 1 && result <= 5) {
968+
setScaleFactor(audioProcessor.scale);
969+
}
970+
971+
if (result == 10) {
972+
auto param = audioProcessor.params.getParameter("reuse_voices");
973+
param->setValueNotifyingHost(reuseVoices ? 0.f : 1.f);
974+
}
975+
if (result == 11) {
976+
auto param = audioProcessor.params.getParameter("stereoizer");
977+
param->setValueNotifyingHost(stereoizer ? 0.f : 1.f);
978+
}
979+
});
980+
}
981+
950982
void RipplerXAudioProcessorEditor::showMalletMenu()
951983
{
952984
auto malletType = (int)audioProcessor.params.getRawParameterValue("mallet_type")->load() + 1;

src/PluginEditor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ class RipplerXAudioProcessorEditor : public juce::AudioProcessorEditor, private
3434
void paint (juce::Graphics&) override;
3535
void resized() override;
3636
void repaintVelSliders ();
37+
void showSettingsMenu();
3738
void showMalletMenu();
3839
void showModelMenu(bool AorB);
3940
void showPartialsMenu(bool AorB);
41+
void drawGear(Graphics& g, Rectangle<int> bounds, float radius, int segs, Colour color, Colour background);
4042

4143
private:
4244
RipplerXAudioProcessor& audioProcessor;
@@ -53,12 +55,11 @@ class RipplerXAudioProcessorEditor : public juce::AudioProcessorEditor, private
5355
ImageButton logo;
5456
ImageButton sun;
5557
ImageButton moon;
56-
Label sizeLabel;
57-
ComboBox sizeMenu;
5858
Label polyLabel;
5959
ComboBox polyMenu;
6060
TextButton velButton;
6161
ComboBox presetMenu;
62+
TextButton settingsBtn;
6263
#if defined(DEBUG)
6364
juce::TextButton presetExport;
6465
#endif
@@ -136,7 +137,6 @@ class RipplerXAudioProcessorEditor : public juce::AudioProcessorEditor, private
136137
Label bendLabel;
137138
std::unique_ptr<Pitch>bendPitch;
138139
std::unique_ptr<Rotary> gain;
139-
TextButton stereoizerBtn;
140140

141141
TooltipWindow tooltipWindow;
142142
juce::MidiKeyboardComponent keyboardComponent;

src/PluginProcessor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ RipplerXAudioProcessor::RipplerXAudioProcessor()
9191
std::make_unique<juce::AudioParameterFloat>("gain", "Res Gain", -24.0f, 24.0f, 0.0f),
9292
std::make_unique<juce::AudioParameterInt>("bend_range", "PitchBend Range", 1, 24, 2),
9393
std::make_unique<juce::AudioParameterBool>("stereoizer", "Stereoizer", true),
94+
std::make_unique<juce::AudioParameterBool>("reuse_voices", "Reuse Voices", false),
9495
}),
9596
mtsClientPtr{nullptr}
9697
#endif
@@ -379,12 +380,13 @@ bool RipplerXAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts)
379380

380381
int RipplerXAudioProcessor::pickVoice(int note) {
381382
int pick = 0;
383+
bool reuseVoices = (bool)params.getRawParameterValue("reuse_voices")->load();
382384

383385
for (int i = 1; i < polyphony; ++i) {
384386
const auto& v1 = voices[i];
385387
const auto& v2 = voices[pick];
386388

387-
if (v1->note == note) {
389+
if (v1->note == note && reuseVoices) {
388390
pick = i;
389391
}
390392
else if (!v1->isPressed && !v2->isPressed) {

0 commit comments

Comments
 (0)