#pragma once #include #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 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 oscAComponents, oscBComponents; // --- FILTER --- Panel filter1Panel { "Filter 1" }, filter2Panel { "Filter 2" }, routingPanel { "Routing" }; FilterDisplay filter1Display, filter2Display; // --- MOD --- std::array envPanels { { Panel ("Env 1 (Amp)"), Panel ("Env 2 (Filter)"), Panel ("Env 3"), Panel ("Env 4") } }; std::array envDisplays; std::array lfoPanels { { Panel ("LFO 1"), Panel ("LFO 2"), Panel ("LFO 3"), Panel ("LFO 4") } }; std::array 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 fxPanels; std::array fxTypeCombos; std::array, kNumFxSlots> fxKnobs; std::array fxUp, fxDown; // --- MACRO --- std::array macroPanels; std::array macroKnobs; Panel macroAssignPanel { "Macro Assignments" }; juce::ComboBox macroAssignTarget; juce::ComboBox macroAssignIndex; Knob macroDepthKnob { "Depth" }; juce::TextButton macroAssignButton, macroClearButton; juce::TextEditor macroList; // --- attachments --- std::vector> sliderAttachments; std::vector> comboAttachments; int currentScaleIndex = -1; // --- helpers --- Knob* makeKnob (juce::Component* parent, const juce::String& name, const juce::String& paramId, std::function 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