diff --git a/Source/LookAndFeel.cpp b/Source/LookAndFeel.cpp index a46634ab..152ecc5d 100644 --- a/Source/LookAndFeel.cpp +++ b/Source/LookAndFeel.cpp @@ -92,7 +92,13 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() { } void OscirenderLookAndFeel::drawLabel(juce::Graphics& g, juce::Label& label) { - g.setColour(label.findColour(juce::Label::backgroundColourId)); + label.setRepaintsOnMouseActivity(true); + auto baseColour = label.findColour(juce::Label::backgroundColourId); + if (label.isEditable()) { + label.setMouseCursor(juce::MouseCursor::IBeamCursor); + baseColour = LookAndFeelHelpers::createBaseColour(baseColour, false, label.isMouseOver(true), false, label.isEnabled()); + } + g.setColour(baseColour); g.fillRoundedRectangle(label.getLocalBounds().toFloat(), RECT_RADIUS); if (! label.isBeingEdited()) @@ -113,13 +119,17 @@ void OscirenderLookAndFeel::drawLabel(juce::Graphics& g, juce::Label& label) { } else if (label.isEnabled()) { - g.setColour (label.findColour (juce::Label::outlineColourId)); + auto outlineColour = label.findColour(juce::Label::outlineColourId); + if (label.isEditable()) { + outlineColour = LookAndFeelHelpers::createBaseColour(outlineColour, false, label.isMouseOver(true), false, label.isEnabled()); + } + g.setColour(outlineColour); + g.drawRoundedRectangle(label.getLocalBounds().toFloat(), RECT_RADIUS, 1); } - - g.drawRoundedRectangle(label.getLocalBounds().toFloat(), RECT_RADIUS, 1); } void OscirenderLookAndFeel::fillTextEditorBackground(juce::Graphics& g, int width, int height, juce::TextEditor& textEditor) { + textEditor.setRepaintsOnMouseActivity(true); if (dynamic_cast (textEditor.getParentComponent()) != nullptr) { g.setColour (textEditor.findColour (juce::TextEditor::backgroundColourId)); @@ -130,7 +140,9 @@ void OscirenderLookAndFeel::fillTextEditorBackground(juce::Graphics& g, int widt } else { - g.setColour (textEditor.findColour (juce::TextEditor::backgroundColourId)); + auto backgroundColour = textEditor.findColour (juce::TextEditor::backgroundColourId); + auto baseColour = LookAndFeelHelpers::createBaseColour(backgroundColour, false, textEditor.isMouseOver(true), false, textEditor.isEnabled()); + g.setColour(baseColour); g.fillRoundedRectangle(textEditor.getLocalBounds().toFloat(), RECT_RADIUS); } } @@ -147,7 +159,9 @@ void OscirenderLookAndFeel::drawTextEditorOutline(juce::Graphics& g, int width, } else { - g.setColour (textEditor.findColour (juce::TextEditor::outlineColourId)); + auto outlineColour = textEditor.findColour(juce::TextEditor::outlineColourId); + outlineColour = LookAndFeelHelpers::createBaseColour(outlineColour, false, textEditor.isMouseOver(true), false, textEditor.isEnabled()); + g.setColour(outlineColour); g.drawRoundedRectangle(0, 0, width, height, RECT_RADIUS, 1.0f); } } @@ -155,13 +169,11 @@ void OscirenderLookAndFeel::drawTextEditorOutline(juce::Graphics& g, int width, void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int height, bool, int, int, int, int, juce::ComboBox& box) { juce::Rectangle boxBounds{0, 0, width, height}; + box.setMouseCursor(juce::MouseCursor::PointingHandCursor); g.setColour(box.findColour(juce::ComboBox::backgroundColourId)); g.fillRoundedRectangle(boxBounds.toFloat(), RECT_RADIUS); - g.setColour(box.findColour(juce::ComboBox::outlineColourId).withAlpha(box.isEnabled() ? 1.0f : 0.5f)); - g.drawRoundedRectangle(boxBounds.toFloat(), RECT_RADIUS, 1.0f); - juce::Rectangle arrowZone{width - 15, 0, 10, height}; juce::Path path; path.startNewSubPath((float)arrowZone.getX(), (float)arrowZone.getCentreY() - 3.0f); @@ -174,6 +186,7 @@ void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int heigh } void OscirenderLookAndFeel::positionComboBoxText(juce::ComboBox& box, juce::Label& label) { + label.setMouseCursor(juce::MouseCursor::PointingHandCursor); label.setBounds(1, 1, box.getWidth() - 15, box.getHeight() - 2); label.setFont(getComboBoxFont(box)); } @@ -274,17 +287,10 @@ void OscirenderLookAndFeel::drawButtonBackground(juce::Graphics& g, juce::Button auto bounds = button.getLocalBounds().toFloat().reduced(0.5f, 0.5f); - auto baseColour = backgroundColour.withMultipliedSaturation(button.hasKeyboardFocus(true) ? 1.3f : 0.9f) - .withMultipliedAlpha(button.isEnabled() ? 1.0f : 0.5f); - - if (shouldDrawButtonAsDown || shouldDrawButtonAsHighlighted) - baseColour = baseColour.contrasting(shouldDrawButtonAsDown ? 0.2f : 0.05f); + auto baseColour = LookAndFeelHelpers::createBaseColour(backgroundColour, button.hasKeyboardFocus(true), shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown, button.isEnabled()); g.setColour(baseColour); g.fillRoundedRectangle(bounds, RECT_RADIUS); - - g.setColour(button.findColour(juce::ComboBox::outlineColourId)); - g.drawRoundedRectangle(bounds, RECT_RADIUS, 1.0f); } void OscirenderLookAndFeel::drawMenuBarBackground(juce::Graphics& g, int width, int height, bool, juce::MenuBarComponent& menuBar) { @@ -330,4 +336,4 @@ juce::CodeEditorComponent::ColourScheme OscirenderLookAndFeel::getDefaultColourS } return cs; -} \ No newline at end of file +} diff --git a/Source/LookAndFeel.h b/Source/LookAndFeel.h index 04b146fb..bcac000c 100644 --- a/Source/LookAndFeel.h +++ b/Source/LookAndFeel.h @@ -12,10 +12,10 @@ enum ColourIds { }; namespace Colours { - const juce::Colour dark{0xff353535}; - const juce::Colour darker{0xff212121}; + const juce::Colour dark{0xff585858}; + const juce::Colour darker{0xff454545}; const juce::Colour veryDark{0xff111111}; - const juce::Colour grey{0xff555555}; + const juce::Colour grey{0xff6c6c6c}; const juce::Colour accentColor{0xff00cc00}; } @@ -36,22 +36,18 @@ namespace Dracula { namespace LookAndFeelHelpers { - static juce::Colour createBaseColour (juce::Colour buttonColour, - bool hasKeyboardFocus, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) noexcept - { + static juce::Colour createBaseColour(juce::Colour buttonColour, bool hasKeyboardFocus, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown, bool isEnabled) noexcept { const float sat = hasKeyboardFocus ? 1.3f : 0.9f; - const juce::Colour baseColour (buttonColour.withMultipliedSaturation (sat)); + const juce::Colour baseColour(buttonColour.withMultipliedSaturation(sat).withMultipliedAlpha(isEnabled ? 1.0f : 0.5f)); - if (shouldDrawButtonAsDown) return baseColour.contrasting (0.2f); - if (shouldDrawButtonAsHighlighted) return baseColour.contrasting (0.1f); + if (shouldDrawButtonAsDown) return baseColour.contrasting (0.3f); + if (shouldDrawButtonAsHighlighted) return baseColour.contrasting (0.15f); return baseColour; } - static juce::TextLayout layoutTooltipText (const juce::String& text, juce::Colour colour) noexcept - { + + static juce::TextLayout layoutTooltipText(const juce::String& text, juce::Colour colour) noexcept { const float tooltipFontSize = 13.0f; const int maxToolTipWidth = 400; diff --git a/Source/components/EffectComponent.cpp b/Source/components/EffectComponent.cpp index 307e6fe3..8a2431a3 100644 --- a/Source/components/EffectComponent.cpp +++ b/Source/components/EffectComponent.cpp @@ -181,7 +181,14 @@ void EffectComponent::resized() { } void EffectComponent::paint(juce::Graphics& g) { - g.fillAll(findColour(effectComponentBackgroundColourId)); + auto bounds = getLocalBounds(); + auto length = effect.parameters.size(); + auto isEnd = index == length - 1; + auto isStart = index == 0; + g.setColour(findColour(effectComponentBackgroundColourId, true)); + juce::Path path; + path.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), OscirenderLookAndFeel::RECT_RADIUS, OscirenderLookAndFeel::RECT_RADIUS, false, isStart, false, isEnd); + g.fillPath(path); } void EffectComponent::parameterValueChanged(int parameterIndex, float newValue) { diff --git a/Source/components/EffectsListComponent.cpp b/Source/components/EffectsListComponent.cpp index cf324436..bfa1e5d0 100644 --- a/Source/components/EffectsListComponent.cpp +++ b/Source/components/EffectsListComponent.cpp @@ -1,9 +1,11 @@ #include "EffectsListComponent.h" #include "SvgButton.h" #include "../PluginEditor.h" +#include "../LookAndFeel.h" -EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, Effect& effect) : DraggableListBoxItem(lb, data, rn), effect(effect), audioProcessor(data.audioProcessor), editor(data.editor) { - auto parameters = effect.parameters; +EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, Effect& effect) : DraggableListBoxItem(lb, data, rn), +effect(effect), audioProcessor(data.audioProcessor), editor(data.editor) { + auto parameters = effect.parameters; for (int i = 0; i < parameters.size(); i++) { std::shared_ptr effectComponent = std::make_shared(audioProcessor, effect, i); selected.setToggleState(effect.enabled == nullptr || effect.enabled->getValue(), juce::dontSendNotification); @@ -24,6 +26,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList data.setSelected(rowNum, selected.getToggleState()); list.setEnabled(selected.getToggleState()); } + repaint(); }; auto component = createComponent(parameters[i]); @@ -34,6 +37,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList listModel.addComponent(effectComponent); } + list.setColour(effectComponentBackgroundColourId, juce::Colours::transparentBlack.withAlpha(0.2f)); list.setModel(&listModel); list.setRowHeight(ROW_HEIGHT); list.updateContent(); @@ -46,10 +50,12 @@ EffectsListComponent::~EffectsListComponent() { } void EffectsListComponent::paint(juce::Graphics& g) { - auto bounds = getLocalBounds(); + auto bounds = getLocalBounds().removeFromLeft(LEFT_BAR_WIDTH); g.setColour(findColour(effectComponentHandleColourId)); - bounds.removeFromBottom(2); - g.fillRect(bounds); + bounds.removeFromBottom(PADDING); + juce::Path path; + path.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), OscirenderLookAndFeel::RECT_RADIUS, OscirenderLookAndFeel::RECT_RADIUS, true, false, true, false); + g.fillPath(path); g.setColour(juce::Colours::white); // draw drag and drop handle using circles double size = 4; @@ -67,18 +73,23 @@ void EffectsListComponent::paint(juce::Graphics& g) { } void EffectsListComponent::paintOverChildren(juce::Graphics& g) { + g.setColour(juce::Colours::black.withAlpha(0.3f)); + auto bounds = list.getBounds(); + bounds.removeFromBottom(PADDING); + juce::Path path; + path.addRoundedRectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), OscirenderLookAndFeel::RECT_RADIUS, OscirenderLookAndFeel::RECT_RADIUS, false, true, false, true); + if (!selected.getToggleState()) { - g.setColour(juce::Colours::black.withAlpha(0.3f)); - auto bounds = list.getBounds(); - bounds.removeFromBottom(2); - g.fillRect(bounds); + g.fillPath(path); } } void EffectsListComponent::resized() { auto area = getLocalBounds(); - area.removeFromLeft(20); - selected.setBounds(area.removeFromLeft(30).withSizeKeepingCentre(30, 20)); + auto leftBar = area.removeFromLeft(LEFT_BAR_WIDTH); + leftBar.removeFromLeft(20); + area.removeFromRight(PADDING); + selected.setBounds(leftBar.withSizeKeepingCentre(30, 20)); list.setBounds(area); } @@ -101,7 +112,7 @@ std::shared_ptr EffectsListComponent::createComponent(EffectPar int EffectsListBoxModel::getRowHeight(int row) { auto data = (AudioEffectListBoxItemData&)modelData; - return data.getEffect(row)->parameters.size() * EffectsListComponent::ROW_HEIGHT + 2; + return data.getEffect(row)->parameters.size() * EffectsListComponent::ROW_HEIGHT + EffectsListComponent::PADDING; } bool EffectsListBoxModel::hasVariableHeightRows() const { diff --git a/Source/components/EffectsListComponent.h b/Source/components/EffectsListComponent.h index 1187d39d..953828ba 100644 --- a/Source/components/EffectsListComponent.h +++ b/Source/components/EffectsListComponent.h @@ -23,38 +23,38 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData void randomise() { juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock); - for (int i = 0; i < data.size(); i++) { - auto effect = data[i]; - auto id = effect->getId().toLowerCase(); - - if (id.contains("scale") || id.contains("translate") || id.contains("trace")) { - continue; - } - - for (auto& parameter : effect->parameters) { - parameter->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat()); - if (parameter->lfo != nullptr) { - parameter->lfo->setUnnormalisedValueNotifyingHost((int) LfoType::Static); - parameter->lfoRate->setUnnormalisedValueNotifyingHost(1); - - if (juce::Random::getSystemRandom().nextFloat() > 0.8) { - parameter->lfo->setUnnormalisedValueNotifyingHost((int)(juce::Random::getSystemRandom().nextFloat() * (int)LfoType::Noise)); - parameter->lfoRate->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat() * 0.1); - } - } - } - effect->enabled->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat() > 0.7); + for (int i = 0; i < data.size(); i++) { + auto effect = data[i]; + auto id = effect->getId().toLowerCase(); + + if (id.contains("scale") || id.contains("translate") || id.contains("trace")) { + continue; + } + + for (auto& parameter : effect->parameters) { + parameter->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat()); + if (parameter->lfo != nullptr) { + parameter->lfo->setUnnormalisedValueNotifyingHost((int) LfoType::Static); + parameter->lfoRate->setUnnormalisedValueNotifyingHost(1); + + if (juce::Random::getSystemRandom().nextFloat() > 0.8) { + parameter->lfo->setUnnormalisedValueNotifyingHost((int)(juce::Random::getSystemRandom().nextFloat() * (int)LfoType::Noise)); + parameter->lfoRate->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat() * 0.1); + } + } + } + effect->enabled->setValueNotifyingHost(juce::Random::getSystemRandom().nextFloat() > 0.7); } // shuffle precedence - std::random_device rd; + std::random_device rd; std::mt19937 g(rd()); - std::shuffle(data.begin(), data.end(), g); - - for (int i = 0; i < data.size(); i++) { - data[i]->setPrecedence(i); - } - + std::shuffle(data.begin(), data.end(), g); + + for (int i = 0; i < data.size(); i++) { + data[i]->setPrecedence(i); + } + audioProcessor.updateEffectPrecedence(); } @@ -150,7 +150,9 @@ public: void paintOverChildren(juce::Graphics& g) override; void resized() override; + static const int LEFT_BAR_WIDTH = 50; static const int ROW_HEIGHT = 30; + static const int PADDING = 4; protected: Effect& effect; diff --git a/osci-render.jucer b/osci-render.jucer index ba568862..fd7d0741 100644 --- a/osci-render.jucer +++ b/osci-render.jucer @@ -9,9 +9,6 @@ companyEmail="james@ball.sh" defines="NOMINMAX=1"> - - -