Files
serumalt/Source/PluginEditor.h
T
biggy facd5c5b5e chore: move build output under build/ and scripts into scripts/
Layout:
- scripts/ holds the four build scripts plus the new clean.sh
- cmake/ holds mingw64-toolchain.cmake
- the scripts default to build/linux, build/macos, build/windows, build/harness
- docs/ holds the audit documents, with the round 1 task list archived

Cleanup:
- scripts/clean.sh removes generated output, with --dry-run, --staging,
  --legacy and --all, and refuses tracked, protected or outside paths
- the Windows VST3 manifest now comes from cmake/moduleinfo.json.in, so its
  version, vendor and class IDs follow cmake/Plugin.cmake instead of a
  hand-written heredoc that could drift
- deleted the unused Source/GUI/Slider, which no code constructed
- fixed the hidden double processBlock overload: three warning lines to zero
- unslopped the build scripts, the two .cjs helpers and the CMake comments
- .gitignore covers the upstream JUCE Projucer and DemoRunner binaries

Verified: five scripts pass bash -n; the harness passes CTest with zero
warning lines; the Linux VST3 and Standalone link; the Windows cross-build
passes its x86-64, runtime-import and entry-point checks; each configure
exposes only its own targets; and a full build leaves Source/ and
third_party/JUCE unchanged. The generated manifest is identical to the
previous hand-written one.
2026-10-06 09:06:53 +02:00

131 lines
4.5 KiB
C++

#pragma once
#include <JuceHeader.h>
#include "PluginProcessor.h"
#include "GUI/Knob.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;
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;
// --- 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;
std::vector<std::unique_ptr<juce::Component>> ownedControls;
// --- 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