Range of sliders is now controllable

pull/170/head
James Ball 2023-07-17 14:37:36 +01:00
rodzic bb91460429
commit 72951d3146
9 zmienionych plików z 137 dodań i 39 usunięć

Wyświetl plik

@ -37,10 +37,6 @@ double Effect::getValue() {
return getValue(0);
}
std::vector<EffectDetails> Effect::getDetails() {
return details;
}
void Effect::setValue(int index, double value) {
details[index].value = value;
}

Wyświetl plik

@ -14,7 +14,6 @@ public:
void apply();
double getValue(int index);
double getValue();
std::vector<EffectDetails> getDetails();
void setValue(int index, double value);
void setValue(double value);
int getPrecedence();
@ -22,8 +21,10 @@ public:
juce::String getId();
juce::String getName();
private:
std::vector<EffectDetails> details;
private:
std::vector<double> smoothValues;
double frequency = 1.0;
int precedence = -1;

Wyświetl plik

@ -5,11 +5,25 @@
struct EffectDetails {
juce::String name;
juce::String id;
double value = 0.0;
double min = 0.0;
double max = 1.0;
double step = 0.001;
bool smoothValueChange = true;
std::atomic<double> value = 0.0;
std::atomic<double> min = 0.0;
std::atomic<double> max = 1.0;
std::atomic<double> step = 0.001;
std::atomic<bool> smoothValueChange = true;
EffectDetails(juce::String name, juce::String id, double value, double min, double max, double step, bool smoothValueChange) : name(name), id(id), value(value), min(min), max(max), step(step), smoothValueChange(smoothValueChange) {}
// COPY CONSTRUCTOR SHOULD ONLY BE USED BEFORE
// THE OBJECT IS USED IN MULTIPLE THREADS
EffectDetails(const EffectDetails& other) {
name = other.name;
id = other.id;
value.store(other.value.load());
min.store(other.min.load());
max.store(other.max.load());
step.store(other.step.load());
smoothValueChange.store(other.smoothValueChange.load());
}
};
class EffectApplication {

Wyświetl plik

@ -1,16 +1,14 @@
#include "EffectComponent.h"
EffectComponent::EffectComponent(EffectDetails details) : details(details) {
EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), index(index) {
componentSetup();
slider.setRange(details.min, details.max, details.step);
slider.setValue(details.value, juce::dontSendNotification);
}
EffectComponent::EffectComponent(EffectDetails details, bool checkboxVisible) : EffectComponent(details) {
setCheckboxVisible(checkboxVisible);
EffectComponent::EffectComponent(Effect& effect, int index, bool checkboxVisible) : EffectComponent(effect, index) {
setCheckboxVisible(checkboxVisible);
}
EffectComponent::EffectComponent(Effect& effect) : EffectComponent(effect.getDetails()[0]) {}
EffectComponent::EffectComponent(Effect& effect) : EffectComponent(effect, 0) {}
EffectComponent::EffectComponent(Effect& effect, bool checkboxVisible) : EffectComponent(effect) {
setCheckboxVisible(checkboxVisible);
@ -20,10 +18,32 @@ void EffectComponent::componentSetup() {
addAndMakeVisible(slider);
addAndMakeVisible(selected);
EffectDetails details = effect.details[index];
slider.setRange(details.min, details.max, details.step);
slider.setValue(details.value, juce::dontSendNotification);
slider.setSliderStyle(juce::Slider::LinearHorizontal);
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
selected.setToggleState(false, juce::dontSendNotification);
min.textBox.setValue(details.min, juce::dontSendNotification);
max.textBox.setValue(details.max, juce::dontSendNotification);
min.textBox.onValueChange = [this]() {
effect.details[index].min = min.textBox.getValue();
slider.setRange(effect.details[index].min, effect.details[index].max, effect.details[index].step);
};
max.textBox.onValueChange = [this]() {
effect.details[index].max = max.textBox.getValue();
slider.setRange(effect.details[index].min, effect.details[index].max, effect.details[index].step);
};
popupLabel.setText(details.name + " Settings", juce::dontSendNotification);
popupLabel.setJustificationType(juce::Justification::centred);
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
}
@ -50,7 +70,19 @@ void EffectComponent::resized() {
void EffectComponent::paint(juce::Graphics& g) {
g.fillAll(juce::Colours::black);
g.setColour(juce::Colours::white);
g.drawText(details.name, textBounds, juce::Justification::left);
g.drawText(effect.details[index].name, textBounds, juce::Justification::left);
}
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
juce::PopupMenu menu;
menu.addCustomItem(1, popupLabel, 200, 30, false);
menu.addCustomItem(2, min, 160, 40, false);
menu.addCustomItem(3, max, 160, 40, false);
menu.showMenuAsync(juce::PopupMenu::Options(), [this](int result) {
});
}
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {

Wyświetl plik

@ -2,24 +2,27 @@
#include <JuceHeader.h>
#include "../PluginProcessor.h"
#include "../audio/Effect.h"
#include "LabelledTextBox.h"
class EffectComponent : public juce::Component {
public:
EffectComponent(EffectDetails details);
EffectComponent(EffectDetails details, bool checkboxVisible);
EffectComponent(Effect& effect, int index);
EffectComponent(Effect& effect, int index, bool checkboxVisible);
EffectComponent(Effect& effect);
EffectComponent(Effect& effect, bool checkboxVisible);
~EffectComponent();
void resized() override;
void paint(juce::Graphics& g) override;
void mouseDown(const juce::MouseEvent& event) override;
void setCheckboxVisible(bool visible);
void setComponent(std::shared_ptr<juce::Component> component);
juce::Slider slider;
EffectDetails details;
Effect& effect;
int index;
juce::ToggleButton selected;
private:
@ -28,5 +31,9 @@ private:
juce::Rectangle<int> textBounds;
std::shared_ptr<juce::Component> component;
juce::Label popupLabel;
LabelledTextBox min{"Min"};
LabelledTextBox max{"Max"};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponent)
};

Wyświetl plik

@ -1,40 +1,40 @@
#include "EffectsListComponent.h"
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
auto details = effect->getDetails();
auto details = effect->details;
for (int i = 0; i < details.size(); i++) {
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(details[i], i == 0);
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(*effect, i, i == 0);
// using weak_ptr to avoid circular reference and memory leak
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
if (auto effectComponent = weakEffectComponent.lock()) {
this->effect->setValue(i, effectComponent->slider.getValue());
}
};
};
if (i == 0) {
bool isSelected = false;
if (i == 0) {
bool isSelected = false;
{
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
// check if effect is in audioProcessor enabled effects
for (auto processorEffect : data.audioProcessor.enabledEffects) {
if (processorEffect->getId() == effect->getId()) {
isSelected = true;
break;
{
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
// check if effect is in audioProcessor enabled effects
for (auto processorEffect : data.audioProcessor.enabledEffects) {
if (processorEffect->getId() == effect->getId()) {
isSelected = true;
break;
}
}
}
}
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
effectComponent->selected.onClick = [this, weakEffectComponent] {
if (auto effectComponent = weakEffectComponent.lock()) {
auto data = (AudioEffectListBoxItemData&)modelData;
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
data.setSelected(rowNum, effectComponent->selected.getToggleState());
}
};
}
};
}
listModel.addComponent(effectComponent);
}
@ -81,7 +81,7 @@ void EffectsListComponent::resized() {
int EffectsListBoxModel::getRowHeight(int row) {
auto data = (AudioEffectListBoxItemData&)modelData;
return data.getEffect(row)->getDetails().size() * 30;
return data.getEffect(row)->details.size() * 30;
}
bool EffectsListBoxModel::hasVariableHeightRows() const {

Wyświetl plik

@ -0,0 +1,25 @@
#pragma once
#include <JuceHeader.h>
#include "SliderTextBox.h"
class LabelledTextBox : public juce::Component {
public:
LabelledTextBox(juce::String text) {
addAndMakeVisible(label);
addAndMakeVisible(textBox);
label.setText(text, juce::dontSendNotification);
label.setJustificationType(juce::Justification::centredLeft);
label.setFont(juce::Font(14.0f));
}
~LabelledTextBox() override {}
void resized() override {
auto bounds = getLocalBounds();
textBox.setBounds(bounds.removeFromRight(90));
label.setBounds(bounds);
}
juce::Label label;
SliderTextBox textBox;
};

Wyświetl plik

@ -0,0 +1,20 @@
#pragma once
#include <JuceHeader.h>
class SliderTextBox : public juce::Slider {
public:
SliderTextBox() {
double RANGE = 999999;
double step = 0.01;
setRange(-RANGE, RANGE, step);
setTextBoxStyle(juce::Slider::TextBoxAbove, false, 90, getTextBoxHeight());
setSliderStyle(juce::Slider::SliderStyle::IncDecButtons);
setIncDecButtonsMode(juce::Slider::IncDecButtonMode::incDecButtonsDraggable_AutoDirection);
setMouseDragSensitivity(2 * RANGE / step);
setSliderSnapsToMousePosition(false);
setColour(juce::Slider::trackColourId, juce::Colours::transparentBlack);
setSize(60, 20);
}
~SliderTextBox() override {}
};

Wyświetl plik

@ -97,10 +97,13 @@
file="Source/components/EffectsListComponent.cpp"/>
<FILE id="dcLchL" name="EffectsListComponent.h" compile="0" resource="0"
file="Source/components/EffectsListComponent.h"/>
<FILE id="L9DIT2" name="LabelledTextBox.h" compile="0" resource="0"
file="Source/components/LabelledTextBox.h"/>
<FILE id="qIxm1z" name="LuaListComponent.cpp" compile="1" resource="0"
file="Source/components/LuaListComponent.cpp"/>
<FILE id="x0Syav" name="LuaListComponent.h" compile="0" resource="0"
file="Source/components/LuaListComponent.h"/>
<FILE id="QQzSwh" name="SliderTextBox.h" compile="0" resource="0" file="Source/components/SliderTextBox.h"/>
<FILE id="y3UiR0" name="VisualiserComponent.cpp" compile="1" resource="0"
file="Source/components/VisualiserComponent.cpp"/>
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"