diff --git a/res/presets/Init.chowpreset b/res/presets/Init.chowpreset index 5d3b922..cfaaa61 100644 Binary files a/res/presets/Init.chowpreset and b/res/presets/Init.chowpreset differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f2764fb..9d1843f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ target_sources(ChowMultiTool PRIVATE gui/AnalogEQ/AnalogEQPlot.cpp gui/AnalogEQ/EQChyron.cpp + gui/BandSplitter/BandSplitterChyron.cpp gui/BandSplitter/BandSplitterEditor.cpp gui/BandSplitter/BandSplitterPlot.cpp gui/BandSplitter/TriStateButtonAttachment.cpp diff --git a/src/gui/BandSplitter/BandSplitterChyron.cpp b/src/gui/BandSplitter/BandSplitterChyron.cpp new file mode 100644 index 0000000..adb65ab --- /dev/null +++ b/src/gui/BandSplitter/BandSplitterChyron.cpp @@ -0,0 +1,96 @@ +#include "BandSplitterChyron.h" + +namespace gui::band_splitter +{ +BandSplitterChyron::BandSplitterChyron (chowdsp::PluginState& pluginState, + dsp::band_splitter::Params& bandSplitterParameters, + const chowdsp::HostContextProvider& hcp) + : state (pluginState), + bandSplitterParams (bandSplitterParameters), + hostContextProvider (hcp) +{ + updateValues(); + callbacks += + { + pluginState.addParameterListener (*bandSplitterParams.threeBandOnOff, + chowdsp::ParameterListenerThread::MessageThread, + [this] + { + updateValues(); + }), + pluginState.addParameterListener (*bandSplitterParams.fourBandOnOff, + chowdsp::ParameterListenerThread::MessageThread, + [this] + { + updateValues(); + }), + }; +} + +void BandSplitterChyron::updateValues() +{ + cutoffSlider1.reset(); + cutoffSlider2.reset(); + cutoffSlider3.reset(); + + auto bandState = bandSplitterParams.getCurrentBandState(); + cutoffSlider1.emplace (state, bandSplitterParams.cutoff.get(), &hostContextProvider); + if (bandState == dsp::band_splitter::BandState::TwoBands) + cutoffSlider1->setName ("Cutoff"); + else + cutoffSlider1->setName ("Cutoff Low"); + addAndMakeVisible (*cutoffSlider1); + + if (bandState != dsp::band_splitter::BandState::TwoBands) + { + cutoffSlider2.emplace (state, bandSplitterParams.cutoff2.get(), &hostContextProvider); + if (bandState == dsp::band_splitter::BandState::ThreeBands) + cutoffSlider2->setName ("Cutoff High"); + else + cutoffSlider2->setName ("Cutoff Mid"); + addAndMakeVisible (*cutoffSlider2); + } + if (bandState == dsp::band_splitter::BandState::FourBands) + { + cutoffSlider3.emplace (state, bandSplitterParams.cutoff3.get(), &hostContextProvider); + cutoffSlider3->setName ("Cutoff High"); + addAndMakeVisible (*cutoffSlider3); + } + resized(); +} + +void BandSplitterChyron::resized() +{ + auto bounds = getLocalBounds(); + const auto sliderBounds = bounds.withHeight (proportionOfHeight (1.0f / 3.0f)); + + if (cutoffSlider2.has_value() && cutoffSlider3.has_value()) + { + const auto fourthHeight = proportionOfHeight (1.0f / 4.0f); + cutoffSlider1->setBounds (sliderBounds.withCentre ({ bounds.getCentreX(), fourthHeight }).reduced (proportionOfWidth (0.025f), 0)); + cutoffSlider2->setBounds (sliderBounds.withCentre ({ bounds.getCentreX(), 2 * fourthHeight }).reduced (proportionOfWidth (0.025f), 0)); + cutoffSlider3->setBounds (sliderBounds.withCentre ({ bounds.getCentreX(), 3 * fourthHeight }).reduced (proportionOfWidth (0.025f), 0)); + } + else if (cutoffSlider2.has_value()) + { + const auto thirdHeight = proportionOfHeight (1.0f / 3.0f); + cutoffSlider1->setBounds (sliderBounds.withCentre ({ bounds.getCentreX(), thirdHeight }).reduced (proportionOfWidth (0.025f), 0)); + cutoffSlider2->setBounds (sliderBounds.withCentre ({ bounds.getCentreX(), 2 * thirdHeight }).reduced (proportionOfWidth (0.025f), 0)); + } + else + { + cutoffSlider1->setBounds (sliderBounds.withCentre (bounds.getCentre()).reduced (proportionOfWidth (0.025f), 0)); + } +} + +void BandSplitterChyron::paint (juce::Graphics& g) +{ + const auto bounds = getLocalBounds(); + + g.setColour (juce::Colours::black.withAlpha (0.75f)); + g.fillRoundedRectangle (bounds.toFloat(), 2.5f); + + g.setColour (colours::linesColour); + g.drawRoundedRectangle (bounds.toFloat(), 2.5f, 1.0f); +} +} // namespace gui::band_splitter \ No newline at end of file diff --git a/src/gui/BandSplitter/BandSplitterChyron.h b/src/gui/BandSplitter/BandSplitterChyron.h new file mode 100644 index 0000000..19c313b --- /dev/null +++ b/src/gui/BandSplitter/BandSplitterChyron.h @@ -0,0 +1,33 @@ +#pragma once + +#include "dsp/BandSplitter/BandSplitterProcessor.h" +#include "gui/Shared/Colours.h" +#include "gui/Shared/Fonts.h" +#include "gui/Shared/TextSlider.h" + +namespace gui::band_splitter +{ +class BandSplitterChyron : public juce::Component +{ +public: + BandSplitterChyron (chowdsp::PluginState& pluginState, + dsp::band_splitter::Params& bandSplitterParameters, + const chowdsp::HostContextProvider& hcp); + void updateValues(); + void resized() override; + void paint (juce::Graphics& g) override; + +private: + chowdsp::PluginState& state; + dsp::band_splitter::Params& bandSplitterParams; + + std::optional cutoffSlider1; + std::optional cutoffSlider2; + std::optional cutoffSlider3; + + chowdsp::ScopedCallbackList callbacks; + const chowdsp::HostContextProvider& hostContextProvider; + + SharedFonts fonts; +}; +} // namespace gui::band_splitter \ No newline at end of file diff --git a/src/gui/BandSplitter/BandSplitterPlot.cpp b/src/gui/BandSplitter/BandSplitterPlot.cpp index f578ed1..4e9bed2 100644 --- a/src/gui/BandSplitter/BandSplitterPlot.cpp +++ b/src/gui/BandSplitter/BandSplitterPlot.cpp @@ -98,7 +98,8 @@ BandSplitterPlot::BandSplitterPlot (State& pluginState, cutoffSlider (*bandSplitParams.cutoff, *this, pluginState, hcp), cutoff2Slider (*bandSplitParams.cutoff2, *this, pluginState, hcp), cutoff3Slider (*bandSplitParams.cutoff3, *this, pluginState, hcp), - spectrumTasks (splitterSpectrumTasks) + spectrumTasks (splitterSpectrumTasks), + chyron (pluginState, bandSplitParams, hcp) { addMouseListener (this, true); extraState.isEditorOpen.store (true); @@ -109,6 +110,10 @@ BandSplitterPlot::BandSplitterPlot (State& pluginState, cutoff2Slider.setVisible (bandSplitterParams.threeBandOnOff->get()); cutoff3Slider.setVisible (bandSplitterParams.fourBandOnOff->get()); + plotComp.setInterceptsMouseClicks (false, false); + plotComp.parent = this; + addAndMakeVisible (plotComp); + for (int bandIndex = 0; bandIndex < numBands; ++bandIndex) setFilterActive (bandIndex, true); @@ -170,6 +175,9 @@ BandSplitterPlot::BandSplitterPlot (State& pluginState, } }), }; + addAndMakeVisible (chyron); + chyron.toFront (false); + updateFilterSlope(); updateSpectrumPlots(); } @@ -240,28 +248,21 @@ void BandSplitterPlot::paintOverChildren (juce::Graphics& g) { 0.0f }, colours::majorLinesColour, colours::minorLinesColour); - - g.setColour (colours::plotColour); - g.strokePath (getPath (0), juce::PathStrokeType { 2.0f }); - g.strokePath (getPath (1), juce::PathStrokeType { 2.0f }); - - auto bandState = bandSplitterParams.getCurrentBandState(); - if (bandState == BandState::FourBands || bandState == BandState::ThreeBands) - { - g.strokePath (getPath (2), juce::PathStrokeType { 2.0f }); - g.strokePath (getPath (3), juce::PathStrokeType { 2.0f }); - } - if (bandState == BandState::FourBands) - { - g.strokePath (getPath (4), juce::PathStrokeType { 2.0f }); - g.strokePath (getPath (5), juce::PathStrokeType { 2.0f }); - } } void BandSplitterPlot::resized() { chowdsp::EQ::EqualizerPlot::resized(); + plotComp.setBounds (getLocalBounds()); + const auto pad = proportionOfWidth (0.005f); + const auto chyronWidth = proportionOfWidth (0.20f); + const auto chyronHeight = proportionOfWidth (0.1f); + chyron.setBounds (getWidth() - pad - chyronWidth, + getHeight() - pad - chyronHeight - proportionOfHeight (0.075f), + chyronWidth, + chyronHeight); + const auto bounds = getLocalBounds(); for (auto [_, spectrum] : spectrumAnalysers) spectrum->setBounds (bounds); @@ -371,4 +372,23 @@ const chowdsp::FreqHzParameter::Ptr& BandSplitterPlot::getCutoffParam (int bandI else return bandParams.cutoff3; }; + +void BandSplitterPlot::FilterPlotComp::paint (juce::Graphics& g) +{ + g.setColour (colours::plotColour); + g.strokePath (parent->getPath (0), juce::PathStrokeType { 2.0f }); + g.strokePath (parent->getPath (1), juce::PathStrokeType { 2.0f }); + + auto bandState = parent->bandSplitterParams.getCurrentBandState(); + if (bandState == BandState::FourBands || bandState == BandState::ThreeBands) + { + g.strokePath (parent->getPath (2), juce::PathStrokeType { 2.0f }); + g.strokePath (parent->getPath (3), juce::PathStrokeType { 2.0f }); + } + if (bandState == BandState::FourBands) + { + g.strokePath (parent->getPath (4), juce::PathStrokeType { 2.0f }); + g.strokePath (parent->getPath (5), juce::PathStrokeType { 2.0f }); + } +} } // namespace gui::band_splitter diff --git a/src/gui/BandSplitter/BandSplitterPlot.h b/src/gui/BandSplitter/BandSplitterPlot.h index 8b50bcc..d707b23 100644 --- a/src/gui/BandSplitter/BandSplitterPlot.h +++ b/src/gui/BandSplitter/BandSplitterPlot.h @@ -1,5 +1,6 @@ #pragma once +#include "BandSplitterChyron.h" #include "dsp/BandSplitter/BandSplitterProcessor.h" #include "gui/Shared/SpectrumAnalyser.h" #include "state/PluginState.h" @@ -27,9 +28,18 @@ class BandSplitterPlot : public chowdsp::EQ::EqualizerPlot void updateSpectrumPlots(); static const chowdsp::FreqHzParameter::Ptr& getCutoffParam (int bandIndex, const dsp::band_splitter::Params& params); + struct FilterPlotComp : juce::Component + { + void paint (juce::Graphics& g); + void resized() { repaint(); } + + BandSplitterPlot* parent = nullptr; + }; + const dsp::band_splitter::Params& bandSplitterParams; dsp::band_splitter::ExtraState& extraState; chowdsp::ScopedCallbackList callbacks; + FilterPlotComp plotComp; struct InternalSlider : juce::Slider { @@ -52,6 +62,7 @@ class BandSplitterPlot : public chowdsp::EQ::EqualizerPlot dsp::band_splitter::BandSplitterSpectrumTasks& spectrumTasks; chowdsp::SmallMap> spectrumAnalysers; + BandSplitterChyron chyron; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BandSplitterPlot) };