Add a floating value label near the cursor while dragging a knob, giving immediate feedback without altering slider behaviour. Inherit SettableTooltipClient on ToggleButton so setTooltip works consistently with knobs and combos. Introduce a shared layout constants namespace in PluginEditor so every panel, row and control position derives from one spacing system. Add tooltips to all knobs, combos, toggles, and buttons. Add Tab/Shift+Tab tab cycling via keyPressed, with a TooltipWindow for hover hints.
133 lines
4.6 KiB
C++
133 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <JuceHeader.h>
|
|
#include "PluginProcessor.h"
|
|
#include "GUI/SerumLookAndFeel.h"
|
|
#include "GUI/Knob.h"
|
|
#include "GUI/Slider.h"
|
|
#include "GUI/ToggleButton.h"
|
|
#include "GUI/Display.h"
|
|
#include "GUI/Panel.h"
|
|
#include "GUI/WaveformDisplay.h"
|
|
#include "GUI/FilterDisplay.h"
|
|
#include "GUI/EnvelopeDisplay.h"
|
|
#include "GUI/LFODisplay.h"
|
|
|
|
namespace serum
|
|
{
|
|
|
|
// ===========================================================================
|
|
// SerumAlt editor: dark vector GUI with a tabbed layout, real-time
|
|
// visualisations, RAVE, macro controls and preset-scale (75%..200%) scaling.
|
|
// ===========================================================================
|
|
class PluginEditor : public juce::AudioProcessorEditor,
|
|
public juce::Timer
|
|
{
|
|
public:
|
|
explicit PluginEditor (SerumAltAudioProcessor& p);
|
|
~PluginEditor() override;
|
|
|
|
void paint (juce::Graphics&) override;
|
|
void resized() override;
|
|
void timerCallback() override;
|
|
bool keyPressed (const juce::KeyPress& key) override;
|
|
|
|
void setTab (int index);
|
|
|
|
private:
|
|
SerumAltAudioProcessor& processor;
|
|
SerumLookAndFeel laf;
|
|
|
|
static constexpr int kBaseW = 1120;
|
|
static constexpr int kBaseH = 740;
|
|
|
|
juce::Component root;
|
|
|
|
// --- tooltips ---
|
|
juce::TooltipWindow tooltipWindow;
|
|
|
|
// --- top bar ---
|
|
std::unique_ptr<juce::Drawable> logo;
|
|
juce::ComboBox presetCombo;
|
|
juce::ComboBox scaleCombo;
|
|
ToggleButton raveButton;
|
|
Knob masterKnob;
|
|
Display masterDisplay;
|
|
|
|
// --- tabs ---
|
|
juce::TextButton tabOsc, tabFilter, tabMod, tabFx, tabMacro;
|
|
juce::Component oscView, filterView, modView, fxView, macroView;
|
|
int currentTab = 0;
|
|
|
|
// --- OSC ---
|
|
Panel oscAPanel { "Oscillator A" }, oscBPanel { "Oscillator B" };
|
|
Panel subPanel { "Sub" }, noisePanel { "Noise" };
|
|
WaveformDisplay oscAWave, oscBWave;
|
|
std::vector<juce::Component*> oscAComponents, oscBComponents;
|
|
|
|
// --- FILTER ---
|
|
Panel filter1Panel { "Filter 1" }, filter2Panel { "Filter 2" }, routingPanel { "Routing" };
|
|
FilterDisplay filter1Display, filter2Display;
|
|
|
|
// --- MOD ---
|
|
std::array<Panel, kNumEnvelopes> envPanels { { Panel ("Env 1 (Amp)"), Panel ("Env 2 (Filter)"),
|
|
Panel ("Env 3"), Panel ("Env 4") } };
|
|
std::array<EnvelopeDisplay, kNumEnvelopes> envDisplays;
|
|
std::array<Panel, kNumLfos> lfoPanels { { Panel ("LFO 1"), Panel ("LFO 2"), Panel ("LFO 3"), Panel ("LFO 4") } };
|
|
std::array<LFODisplay, kNumLfos> lfoDisplays;
|
|
|
|
Panel matrixPanel { "Modulation Matrix" };
|
|
juce::ComboBox modSourceCombo, modTargetCombo;
|
|
Knob modDepthKnob { "Depth" };
|
|
ToggleButton modBipolarToggle;
|
|
juce::TextButton modAddButton, modRemoveButton, modClearButton;
|
|
juce::TextEditor modList;
|
|
|
|
// --- FX ---
|
|
std::array<Panel, kNumFxSlots> fxPanels;
|
|
std::array<juce::ComboBox*, kNumFxSlots> fxTypeCombos;
|
|
std::array<std::vector<Knob*>, kNumFxSlots> fxKnobs;
|
|
std::array<juce::TextButton*, kNumFxSlots> fxUp, fxDown;
|
|
|
|
// --- MACRO ---
|
|
std::array<Panel, kNumMacros> macroPanels;
|
|
std::array<Knob*, kNumMacros> macroKnobs;
|
|
Panel macroAssignPanel { "Macro Assignments" };
|
|
juce::ComboBox macroAssignTarget;
|
|
juce::ComboBox macroAssignIndex;
|
|
Knob macroDepthKnob { "Depth" };
|
|
juce::TextButton macroAssignButton, macroClearButton;
|
|
juce::TextEditor macroList;
|
|
|
|
// --- attachments ---
|
|
std::vector<std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment>> sliderAttachments;
|
|
std::vector<std::unique_ptr<juce::AudioProcessorValueTreeState::ComboBoxAttachment>> comboAttachments;
|
|
|
|
int currentScaleIndex = -1;
|
|
|
|
// --- helpers ---
|
|
Knob* makeKnob (juce::Component* parent, const juce::String& name, const juce::String& paramId,
|
|
std::function<juce::String (float)> fmt = {}, const juce::String& tooltip = {});
|
|
juce::ComboBox* makeCombo (juce::Component* parent, const juce::String& paramId, const juce::StringArray& items,
|
|
const juce::String& tooltip = {});
|
|
ToggleButton* makeToggle (juce::Component* parent, const juce::String& label, const juce::String& paramId,
|
|
const juce::String& tooltip = {});
|
|
void cycleTab (int delta);
|
|
|
|
void buildTopBar();
|
|
void buildOscTab();
|
|
void buildFilterTab();
|
|
void buildModTab();
|
|
void buildFxTab();
|
|
void buildMacroTab();
|
|
void swapFxSlots (int a, int b);
|
|
void applyUiScale();
|
|
void updateVisuals();
|
|
void updateModList();
|
|
void updateMacroList();
|
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginEditor)
|
|
};
|
|
|
|
} // namespace serum
|