Skip to content

Commit 2a64aff

Browse files
authored
Improve SuperMacro display (#368)
- Show a button for number of usages and keep knob enabled - That button if useage > 0 jumps to the usage Assisted-By: Claude Opus 4.7
1 parent 0aad995 commit 2a64aff

5 files changed

Lines changed: 76 additions & 26 deletions

File tree

doc/12_roadmap.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22

33
I have a lot of ideas for a '1.2' version of six sines. Not 2.0. Still compatible. But expanded. Here's my rough list
44

5-
## SuperMacros
6-
7-
- Make 'used' indicator not disabled but rather a glyph of some form
8-
- Rather than gray out, switch on in mod matrix when picked
9-
-
10-
115
## Modulation
126
- Clamp targets
137
- LFO -> M etc... depth as an additive and attenuation target
@@ -21,7 +15,7 @@ new entry project_tests_harness.md records the Catch2 six-sines-test target, the
2115
to add new test files to tests/CMakeLists.txt explicitly. Noted your CLAUDE.md edit (line 32 now acknowledges tests).
2216

2317
## Smaller Things from the crew
24-
- Reaper analyzer z order screwage (what does surge do)
18+
- Unison detune - snap at note on or continuous?
2519
- Now we have DES move MPE to the instance
2620
- if you load a stream which has it from the clap edge set the instance to that
2721
- if you load a patch from an sxsnp ignore the patch setting

src/ui/macro-panel.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ MacroPanel::MacroPanel(SixSinesEditor &e) : jcmp::NamedPanel("Macros"), HasEdito
4949
editor.macroSubPanel->setEnabledState();
5050
};
5151
addAndMakeVisible(*power[i]);
52+
53+
usageButtons[i] = std::make_unique<jcmp::TextPushButton>();
54+
usageButtons[i]->setLabel("0");
55+
usageButtons[i]->setOnCallback([this, i]() { showUsageMenu(i); });
56+
addAndMakeVisible(*usageButtons[i]);
5257
}
5358

5459
highlight = std::make_unique<KnobHighlight>(editor);
@@ -64,7 +69,7 @@ void MacroPanel::resized()
6469
auto y = b.getY();
6570
for (auto i = 0U; i < numMacros; ++i)
6671
{
67-
positionPowerKnobAndLabel(x, y, power[i], knobs[i], labels[i], true);
72+
positionPowerKnobSwitchAndLabel(x, y, power[i], usageButtons[i], knobs[i], labels[i]);
6873
x += uicPowerKnobWidth + uicMargin;
6974
}
7075
}
@@ -92,6 +97,50 @@ void MacroPanel::mouseDown(const juce::MouseEvent &e)
9297
}
9398
}
9499

100+
void MacroPanel::refreshUsage(size_t idx)
101+
{
102+
if (idx >= numMacros)
103+
return;
104+
auto count = editor.macroUsageCache[idx].size();
105+
if (usageButtons[idx])
106+
{
107+
usageButtons[idx]->setLabel(std::to_string(count));
108+
usageButtons[idx]->setEnabled(count > 0);
109+
usageButtons[idx]->repaint();
110+
}
111+
if (labels[idx])
112+
{
113+
labels[idx]->setEnabled(count > 0);
114+
labels[idx]->repaint();
115+
}
116+
}
117+
118+
void MacroPanel::showUsageMenu(size_t idx)
119+
{
120+
if (idx >= numMacros)
121+
return;
122+
auto &uses = editor.macroUsageCache[idx];
123+
if (uses.empty())
124+
return;
125+
126+
auto p = juce::PopupMenu();
127+
p.addSectionHeader(displayShortName(editor, idx));
128+
p.addSeparator();
129+
for (auto &u : uses)
130+
{
131+
auto label = u.nodeLabel + "" + u.targetName + (u.modulated ? " (mod)" : "");
132+
auto refCopy = u;
133+
p.addItem(label,
134+
[w = juce::Component::SafePointer(this), refCopy]()
135+
{
136+
if (w && w->editor.macroSubPanel)
137+
w->editor.macroSubPanel->jumpTo(refCopy);
138+
});
139+
}
140+
p.showMenuAsync(juce::PopupMenu::Options().withParentComponent(&editor),
141+
makeMenuAccessibleButtonCB(usageButtons[idx].get()));
142+
}
143+
95144
void MacroPanel::refreshLabel(size_t idx)
96145
{
97146
if (idx >= numMacros || !labels[idx])

src/ui/macro-panel.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <sst/jucegui/components/Knob.h>
2020
#include <sst/jucegui/components/Label.h>
2121
#include <sst/jucegui/components/ToggleButton.h>
22+
#include <sst/jucegui/components/TextPushButton.h>
2223
#include <sst/jucegui/data/Continuous.h>
2324
#include "six-sines-editor.h"
2425
#include "patch-data-bindings.h"
@@ -39,6 +40,14 @@ struct MacroPanel : jcmp::NamedPanel, HasEditor
3940

4041
void refreshLabel(size_t idx);
4142

43+
// Refresh count button text + enabled state and label enabled state from
44+
// editor.macroUsageCache. Called by SixSinesEditor::recomputeMacroUsage.
45+
void refreshUsage(size_t idx);
46+
47+
// Open popup menu listing every consumer of macro idx; each item jumps to
48+
// that node via macroSubPanel->jumpTo.
49+
void showUsageMenu(size_t idx);
50+
4251
// Single source of truth for macro display names. Short = knob label,
4352
// Full = sub-panel title. Both fall back to "Macro N" when unrenamed.
4453
static std::string displayShortName(const SixSinesEditor &editor, size_t idx)
@@ -72,6 +81,8 @@ struct MacroPanel : jcmp::NamedPanel, HasEditor
7281

7382
std::array<std::unique_ptr<jcmp::ToggleButton>, numMacros> power;
7483
std::array<std::unique_ptr<PatchDiscrete>, numMacros> powerD;
84+
85+
std::array<std::unique_ptr<jcmp::TextPushButton>, numMacros> usageButtons;
7586
};
7687
} // namespace baconpaul::six_sines::ui
7788
#endif // BACONPAUL_SIX_SINES_UI_MACRO_PANEL_H

src/ui/modulation-components.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ template <typename Comp, typename Patch> struct ModulationComponents
232232
SXSNLOG("GenSet action at " << lidx << " with " << sCopy);
233233
if (sCopy == 2048)
234234
SXSNLOG("ERROR: GENSET with sCopy=2048 " << lidx);
235+
// Selecting a MACRO_MOD_k source while macro k is off auto-powers it.
236+
if (sCopy >= ModMatrixConfig::MACRO_MOD_0 &&
237+
sCopy < (int)ModMatrixConfig::MACRO_MOD_0 + (int)numMacros)
238+
{
239+
int k = sCopy - (int)ModMatrixConfig::MACRO_MOD_0;
240+
auto &mp = w->editor.patchCopy.macroNodes[k].macroPower;
241+
if (mp.value < 0.5f)
242+
w->editor.setAndSendParamValue(mp, 1.f);
243+
}
235244
w->editor.setAndSendParamValue(w->patchPtr->modsource[lidx], sCopy);
236245
w->resetSourceLabel(lidx);
237246
if (w->editor.onModulationRoutingChanged)
@@ -292,19 +301,10 @@ template <typename Comp, typename Patch> struct ModulationComponents
292301
// (e.g. EXTEND_M only available in PHASE_REMAP).
293302
std::function<bool(typename Patch::TargetID)> isTargetAvailable{[](auto) { return true; }};
294303

295-
// Universal source filter: greys MACRO_MOD_k when that macro's power is off.
296-
// Panels overriding sourceFilter should fall through to this.
297-
SourceFilterResult sharedSourceFilter(int sid)
298-
{
299-
if (sid >= ModMatrixConfig::MACRO_MOD_0 &&
300-
sid < (int)ModMatrixConfig::MACRO_MOD_0 + (int)numMacros)
301-
{
302-
int k = sid - (int)ModMatrixConfig::MACRO_MOD_0;
303-
if (asComp()->editor.patchCopy.macroNodes[k].macroPower.value < 0.5f)
304-
return SourceFilterResult::Disabled;
305-
}
306-
return SourceFilterResult::Include;
307-
}
304+
// Universal source filter. MACRO_MOD_k is always Include even when macro k
305+
// is off; selecting it auto-powers the macro on (see genSet above). Panels
306+
// overriding sourceFilter should fall through to this.
307+
SourceFilterResult sharedSourceFilter(int /*sid*/) { return SourceFilterResult::Include; }
308308

309309
// Override per-panel to add extra rules; defaults to sharedSourceFilter.
310310
std::function<SourceFilterResult(int)> sourceFilter{[this](int sid)

src/ui/six-sines-editor.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,7 @@ void SixSinesEditor::recomputeMacroUsage()
11021102
if (macroPanel)
11031103
{
11041104
for (size_t i = 0; i < numMacros; ++i)
1105-
{
1106-
auto used = !macroUsageCache[i].empty();
1107-
if (macroPanel->knobs[i])
1108-
macroPanel->knobs[i]->setEnabled(used);
1109-
}
1105+
macroPanel->refreshUsage(i);
11101106
}
11111107
if (macroSubPanel && macroSubPanel->isVisible())
11121108
macroSubPanel->refreshUsedByList();

0 commit comments

Comments
 (0)