Skip to content

Commit cb218fb

Browse files
authored
Small UI fixes and changes (#354)
- Settings panel: reorganize the top into a 4-column grid (Voices/Unison, Play/Porta, Bend/Octave, MPE/Panic) and add an Output Control divider above the Oversampling controls - Macro power: refresh the macro sub-panel's enabled state after the power toggle writes its new value, so the ADSR/LFO/mod widgets no longer latch the stale (pre-toggle) state - Ratio editor: preserve the +1/-1 sign across a write — the cache now survives setValueFromGUI's external-refresh callback, so jogging down from 1 lands on -1 and jogging up from -2 lands on -1 - Bump sst-basic-blocks and pass the new VU peak LPF frequency Assisted-by: Claude Opus 4.7
1 parent b245e6e commit cb218fb

7 files changed

Lines changed: 80 additions & 54 deletions

File tree

src/synth/synth.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ void Synth::setSampleRate(double sampleRate)
166166
monoValues.sr.setSampleRate(internalRate);
167167

168168
lagHandler.setRate(60, blockSize, monoValues.sr.sampleRate);
169-
vuPeak.setSampleRate(monoValues.sr.sampleRate);
169+
vuPeak.setSampleRate(monoValues.sr.sampleRate, 20);
170170
for (int i = 0; i < numOps; ++i)
171171
{
172-
opVuPeak[i].setSampleRate(monoValues.sr.sampleRate);
172+
opVuPeak[i].setSampleRate(monoValues.sr.sampleRate, 20);
173173
}
174174
sampleRateRatio = hostSampleRate / engineSampleRate;
175175

src/ui/macro-panel.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ MacroPanel::MacroPanel(SixSinesEditor &e) : jcmp::NamedPanel("Macros"), HasEdito
3939
createComponent(editor, *this, mn[i].macroPower, power[i], powerD[i], i);
4040
power[i]->setDrawMode(sst::jucegui::components::ToggleButton::DrawMode::GLYPH);
4141
power[i]->setGlyph(sst::jucegui::components::GlyphPainter::POWER);
42+
// The toggle's onBeginEdit calls beginEdit(i) → setSelectedIndex →
43+
// setEnabledState before setValueFromGUI flips macroPower, so the sub-panel
44+
// would latch the stale value. Re-run setEnabledState after the GUI write.
45+
powerD[i]->onGuiSetValue = [this, i]()
46+
{
47+
if (editor.macroSubPanel && editor.macroSubPanel->isVisible() &&
48+
editor.macroSubPanel->index == i)
49+
editor.macroSubPanel->setEnabledState();
50+
};
4251
addAndMakeVisible(*power[i]);
4352
}
4453

src/ui/macro-sub-panel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void MacroSubPanel::setSelectedIndex(size_t i)
108108
w->setEnabledState();
109109
};
110110
editor.componentRefreshByID[mn.envIsMultiplcative.meta.id] = refreshEnabled;
111+
editor.componentRefreshByID[mn.macroPower.meta.id] = refreshEnabled;
111112
envMulD->onGuiSetValue = refreshEnabled;
112113

113114
auto &nameBuf = editor.patchCopy.macroNames[i];

src/ui/playmode-sub-panel.cpp

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ PlayModeSubPanel::PlayModeSubPanel(SixSinesEditor &e) : HasEditor(e)
184184
addAndMakeVisible(*panicButton);
185185
addAndMakeVisible(*panicTitle);
186186

187+
outputControlTitle = std::make_unique<jcmp::RuledLabel>();
188+
outputControlTitle->setText("Output Control");
189+
addAndMakeVisible(*outputControlTitle);
190+
187191
createComponent(editor, *this, editor.patchCopy.output.sampleRateStrategy, srStrat, srStratD);
188192
addAndMakeVisible(*srStrat);
189193
createComponent(editor, *this, editor.patchCopy.output.resampleEngine, rsEng, rsEngD);
@@ -199,61 +203,67 @@ void PlayModeSubPanel::resized()
199203
{
200204
namespace jlo = sst::jucegui::layouts;
201205
auto skinny = uicKnobSize + 30;
202-
auto playRowHeight =
203-
uicTitleLabelInnerBox + 2 * uicLabelHeight + uicMargin + 5 * uicLabelHeight + 6 * uicMargin;
204206

205-
auto outer = jlo::HList().at(uicMargin, 0).withAutoGap(2 * uicMargin);
207+
// Top section: 4 columns, each split into a top sub-section and a bottom sub-section
208+
// col1: Voices / Unison
209+
// col2: Play (mode + triggers + porta)
210+
// col3: Bend / Octave
211+
// col4: MPE / Panic
212+
// The two tallest columns (1 and 2) drive the row height.
213+
auto topRowHeight = uicTitleLabelInnerBox + 7 * uicLabelHeight + 7 * uicMargin;
214+
215+
auto outer = jlo::VList().at(uicMargin, 0).withAutoGap(2 * uicMargin);
216+
217+
auto topRow = jlo::HList().withHeight(topRowHeight).withAutoGap(2 * uicMargin);
206218

207-
// Column 1: voices / bend / octave / mpe / panic
208219
auto col1 = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
209220
col1.add(titleLabelGaplessLayout(voiceLimitL));
210221
col1.add(jlo::Component(*voiceLimit).withHeight(uicLabelHeight));
211-
col1.add(titleLabelGaplessLayout(bendTitle));
212-
col1.add(sideLabel(bUpL, bUp));
213-
col1.add(sideLabel(bDnL, bDn));
214-
col1.add(titleLabelGaplessLayout(tsposeTitle));
215-
col1.add(jlo::Component(*tsposeButton).withHeight(uicLabelHeight));
216-
col1.add(titleLabelGaplessLayout(mpeTitle));
217-
col1.add(jlo::Component(*mpeActiveButton).withHeight(uicLabelHeight));
218-
col1.add(jlo::Component(*mpeRange).withHeight(uicLabelHeight));
219-
col1.add(jlo::Component(*mpeRangeL).withHeight(uicLabelHeight));
220-
col1.add(titleLabelGaplessLayout(panicTitle));
221-
col1.add(jlo::Component(*panicButton).withHeight(uicLabelHeight));
222-
outer.add(col1);
223-
224-
// Column 2: play + unison on top, oversampling below
225-
auto col2 = jlo::VList().withWidth(2 * skinny + 2 * uicMargin).withAutoGap(2 * uicMargin);
226-
227-
auto topRow = jlo::HList().withHeight(playRowHeight).withAutoGap(2 * uicMargin);
228-
229-
auto pml = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
230-
pml.add(titleLabelGaplessLayout(playTitle));
231-
pml.add(jlo::Component(*playMode).withHeight(2 * uicLabelHeight + uicMargin));
232-
pml.add(jlo::Component(*triggerButton).withHeight(uicLabelHeight));
233-
pml.add(jlo::Component(*pianoModeButton).withHeight(uicLabelHeight));
234-
pml.add(jlo::Component(*portaL).withHeight(uicLabelHeight));
235-
pml.add(jlo::Component(*portaTime).withHeight(uicLabelHeight).insetBy(0, 2));
236-
pml.add(jlo::Component(*portaContinuationButton).withHeight(uicLabelHeight));
237-
topRow.add(pml);
238-
239-
auto uml = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
240-
uml.add(titleLabelGaplessLayout(uniTitle));
241-
uml.add(jlo::Component(*uniCt).withHeight(uicLabelHeight));
242-
uml.add(jlo::Component(*uniCtL).withHeight(uicLabelHeight));
243-
uml.add(jlo::Component(*uniRPhase).withHeight(uicLabelHeight));
244-
uml.add(sideLabelSlider(uniSpreadG, uniSpread));
245-
uml.add(sideLabelSlider(uniPanG, uniPan));
246-
topRow.add(uml);
247-
248-
col2.add(topRow);
249-
250-
auto rsl = jlo::VList().withAutoGap(uicMargin);
222+
col1.add(titleLabelGaplessLayout(uniTitle));
223+
col1.add(jlo::Component(*uniCt).withHeight(uicLabelHeight));
224+
col1.add(jlo::Component(*uniCtL).withHeight(uicLabelHeight));
225+
col1.add(jlo::Component(*uniRPhase).withHeight(uicLabelHeight));
226+
col1.add(sideLabelSlider(uniSpreadG, uniSpread));
227+
col1.add(sideLabelSlider(uniPanG, uniPan));
228+
topRow.add(col1);
229+
230+
auto col2 = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
231+
col2.add(titleLabelGaplessLayout(playTitle));
232+
col2.add(jlo::Component(*playMode).withHeight(2 * uicLabelHeight + uicMargin));
233+
col2.add(jlo::Component(*triggerButton).withHeight(uicLabelHeight));
234+
col2.add(jlo::Component(*pianoModeButton).withHeight(uicLabelHeight));
235+
col2.add(jlo::Component(*portaL).withHeight(uicLabelHeight));
236+
col2.add(jlo::Component(*portaTime).withHeight(uicLabelHeight).insetBy(0, 2));
237+
col2.add(jlo::Component(*portaContinuationButton).withHeight(uicLabelHeight));
238+
topRow.add(col2);
239+
240+
auto col3 = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
241+
col3.add(titleLabelGaplessLayout(bendTitle));
242+
col3.add(sideLabel(bUpL, bUp));
243+
col3.add(sideLabel(bDnL, bDn));
244+
col3.add(titleLabelGaplessLayout(tsposeTitle));
245+
col3.add(jlo::Component(*tsposeButton).withHeight(uicLabelHeight));
246+
topRow.add(col3);
247+
248+
auto col4 = jlo::VList().withWidth(skinny).withAutoGap(uicMargin);
249+
col4.add(titleLabelGaplessLayout(mpeTitle));
250+
col4.add(jlo::Component(*mpeActiveButton).withHeight(uicLabelHeight));
251+
col4.add(jlo::Component(*mpeRange).withHeight(uicLabelHeight));
252+
col4.add(jlo::Component(*mpeRangeL).withHeight(uicLabelHeight));
253+
col4.add(titleLabelGaplessLayout(panicTitle));
254+
col4.add(jlo::Component(*panicButton).withHeight(uicLabelHeight));
255+
topRow.add(col4);
256+
257+
outer.add(topRow);
258+
259+
auto bottomWidth = 4 * skinny + 3 * 2 * uicMargin;
260+
outer.add(titleLabelGaplessLayout(outputControlTitle).withWidth(bottomWidth));
261+
262+
auto rsl = jlo::VList().withWidth(bottomWidth).withAutoGap(uicMargin);
251263
rsl.add(titleLabelGaplessLayout(srStratLab));
252264
rsl.add(jlo::Component(*srStrat).withHeight(uicLabelHeight));
253265
rsl.add(jlo::Component(*rsEng).withHeight(uicLabelHeight));
254-
col2.add(rsl);
255-
256-
outer.add(col2);
266+
outer.add(rsl);
257267

258268
outer.doLayout();
259269
}

src/ui/playmode-sub-panel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ struct PlayModeSubPanel : juce::Component, HasEditor
8585

8686
std::unique_ptr<jcmp::TextPushButton> panicButton;
8787

88+
std::unique_ptr<jcmp::RuledLabel> outputControlTitle;
89+
8890
std::unique_ptr<jcmp::RuledLabel> srStratLab;
8991
std::unique_ptr<jcmp::JogUpDownButton> srStrat;
9092
std::unique_ptr<PatchDiscrete> srStratD;

src/ui/segmented-ratio-editor.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,6 @@ void SegmentedRatioEditor::writeDigits(int t1, int t2, int t3)
422422
t3 = 0;
423423
}
424424

425-
cachedT1 = t1;
426-
cachedT2 = t2;
427-
cachedT3 = t3;
428-
digitsValid = true;
429425
auto v = recompose(t1, t2, t3);
430426
if (inOuterGesture)
431427
{
@@ -439,6 +435,14 @@ void SegmentedRatioEditor::writeDigits(int t1, int t2, int t3)
439435
c->setValueFromGUI(v);
440436
onEndEdit();
441437
}
438+
// Restore the cache after setValueFromGUI: the panel wires onGuiSetValue →
439+
// refreshFromExternal, which invalidates digits. +1 and -1 both encode to
440+
// log2(1)=0 in the float, so decompose can't tell them apart; the cache is
441+
// the only thing that keeps the sign at that boundary.
442+
cachedT1 = t1;
443+
cachedT2 = t2;
444+
cachedT3 = t3;
445+
digitsValid = true;
442446
if (editor)
443447
editor->repaint();
444448
repaint();

0 commit comments

Comments
 (0)