kopia lustrzana https://github.com/jameshball/osci-render
Significantly simplify usage of SwitchButtons
rodzic
87edfe0608
commit
96fb3efbb0
|
@ -204,18 +204,6 @@
|
|||
}
|
||||
});
|
||||
|
||||
window.__JUCE__.backend.addEventListener("intensityChanged", intensity => {
|
||||
controls.exposureStops = intensity;
|
||||
});
|
||||
|
||||
window.__JUCE__.backend.addEventListener("persistenceChanged", persistence => {
|
||||
controls.persistence = persistence;
|
||||
});
|
||||
|
||||
window.__JUCE__.backend.addEventListener("hueChanged", hue => {
|
||||
controls.hue = hue;
|
||||
});
|
||||
|
||||
document.addEventListener("dblclick", function() {
|
||||
toggleFullscreen();
|
||||
});
|
||||
|
|
|
@ -688,6 +688,13 @@ function doScriptProcessor(event) {
|
|||
xSamples[i] = dataView.getFloat32(i * 4 * 2, true);
|
||||
ySamples[i] = dataView.getFloat32(i * 4 * 2 + 4, true);
|
||||
}
|
||||
|
||||
const getSettingsFn = Juce.getNativeFunction("getSettings");
|
||||
getSettingsFn().then(settings => {
|
||||
controls.exposureStops = settings.intensity;
|
||||
controls.persistence = settings.persistence;
|
||||
controls.hue = settings.hue;
|
||||
});
|
||||
|
||||
if (controls.sweepOn) {
|
||||
var gain = Math.pow(2.0,controls.mainGain);
|
||||
|
|
|
@ -14,8 +14,6 @@ FrameSettingsComponent::FrameSettingsComponent(OscirenderAudioProcessor& p, Osci
|
|||
addAndMakeVisible(threshold);
|
||||
addAndMakeVisible(stride);
|
||||
|
||||
animate.setTooltip("Enables animation for files that have multiple frames, such as GIFs or Line Art.");
|
||||
sync.setTooltip("Synchronises the animation's framerate with the BPM of your DAW.");
|
||||
offsetLabel.setTooltip("Offsets the animation's start point by a specified number of frames.");
|
||||
|
||||
rateLabel.setText("Frames per Second", juce::dontSendNotification);
|
||||
|
@ -27,23 +25,13 @@ FrameSettingsComponent::FrameSettingsComponent(OscirenderAudioProcessor& p, Osci
|
|||
update();
|
||||
|
||||
auto updateAnimation = [this]() {
|
||||
audioProcessor.animateFrames->setValueNotifyingHost(animate.getToggleState());
|
||||
audioProcessor.animationSyncBPM->setValueNotifyingHost(sync.getToggleState());
|
||||
audioProcessor.animationRate->setUnnormalisedValueNotifyingHost(rateBox.getValue());
|
||||
audioProcessor.animationOffset->setUnnormalisedValueNotifyingHost(offsetBox.getValue());
|
||||
audioProcessor.invertImage->setValueNotifyingHost(invertImage.getToggleState());
|
||||
};
|
||||
|
||||
animate.onClick = updateAnimation;
|
||||
sync.onClick = updateAnimation;
|
||||
rateBox.onFocusLost = updateAnimation;
|
||||
offsetBox.onFocusLost = updateAnimation;
|
||||
|
||||
invertImage.onClick = [this]() {
|
||||
audioProcessor.invertImage->setValue(invertImage.getToggleState());
|
||||
};
|
||||
invertImage.setTooltip("Inverts the image so that dark pixels become light, and vice versa.");
|
||||
|
||||
threshold.slider.onValueChange = [this]() {
|
||||
audioProcessor.imageThreshold->setValue(threshold.slider.getValue());
|
||||
};
|
||||
|
@ -52,35 +40,32 @@ FrameSettingsComponent::FrameSettingsComponent(OscirenderAudioProcessor& p, Osci
|
|||
audioProcessor.imageStride->setValue(stride.slider.getValue());
|
||||
};
|
||||
|
||||
audioProcessor.animateFrames->addListener(this);
|
||||
audioProcessor.animationSyncBPM->addListener(this);
|
||||
audioProcessor.animationRate->addListener(this);
|
||||
audioProcessor.animationOffset->addListener(this);
|
||||
audioProcessor.invertImage->addListener(this);
|
||||
}
|
||||
|
||||
FrameSettingsComponent::~FrameSettingsComponent() {
|
||||
audioProcessor.invertImage->removeListener(this);
|
||||
audioProcessor.animationOffset->removeListener(this);
|
||||
audioProcessor.animationRate->removeListener(this);
|
||||
audioProcessor.animationSyncBPM->removeListener(this);
|
||||
audioProcessor.animateFrames->removeListener(this);
|
||||
}
|
||||
|
||||
void FrameSettingsComponent::resized() {
|
||||
auto area = getLocalBounds().withTrimmedTop(20).reduced(20);
|
||||
double rowHeight = 20;
|
||||
|
||||
auto toggleBounds = area.removeFromTop(rowHeight);
|
||||
auto toggleWidth = juce::jmin(area.getWidth() / 3, 150);
|
||||
|
||||
if (animated) {
|
||||
animate.setBounds(toggleBounds.removeFromLeft(toggleWidth));
|
||||
sync.setBounds(toggleBounds.removeFromLeft(toggleWidth));
|
||||
|
||||
double rowSpace = 10;
|
||||
auto firstColumn = area.removeFromLeft(220);
|
||||
|
||||
auto animateBounds = firstColumn.removeFromTop(rowHeight);
|
||||
animate.setBounds(animateBounds.removeFromLeft(100));
|
||||
sync.setBounds(animateBounds.removeFromLeft(100));
|
||||
firstColumn.removeFromTop(rowSpace);
|
||||
|
||||
animateBounds = firstColumn.removeFromTop(rowHeight);
|
||||
auto animateBounds = firstColumn.removeFromTop(rowHeight);
|
||||
rateLabel.setBounds(animateBounds.removeFromLeft(140));
|
||||
rateBox.setBounds(animateBounds.removeFromLeft(60));
|
||||
firstColumn.removeFromTop(rowSpace);
|
||||
|
@ -91,9 +76,9 @@ void FrameSettingsComponent::resized() {
|
|||
}
|
||||
|
||||
if (image) {
|
||||
invertImage.setBounds(toggleBounds.removeFromLeft(toggleWidth));
|
||||
|
||||
auto secondColumn = area;
|
||||
auto invertBounds = secondColumn.removeFromTop(rowHeight);
|
||||
invertImage.setBounds(invertBounds.removeFromLeft(100));
|
||||
secondColumn.removeFromTop(5);
|
||||
|
||||
rowHeight = 30;
|
||||
|
@ -105,9 +90,6 @@ void FrameSettingsComponent::resized() {
|
|||
void FrameSettingsComponent::update() {
|
||||
rateBox.setValue(audioProcessor.animationRate->getValueUnnormalised(), false, 2);
|
||||
offsetBox.setValue(audioProcessor.animationOffset->getValueUnnormalised(), false, 2);
|
||||
animate.setToggleState(audioProcessor.animateFrames->getValue(), false);
|
||||
sync.setToggleState(audioProcessor.animationSyncBPM->getValue(), false);
|
||||
invertImage.setToggleState(audioProcessor.invertImage->getValue(), false);
|
||||
if (sync.getToggleState()) {
|
||||
rateLabel.setText("Frames per Beat", juce::dontSendNotification);
|
||||
rateLabel.setTooltip("Set the animation's speed in frames per beat.");
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "PluginProcessor.h"
|
||||
#include "components/DoubleTextBox.h"
|
||||
#include "components/EffectComponent.h"
|
||||
#include "components/SwitchButton.h"
|
||||
|
||||
class OscirenderAudioProcessorEditor;
|
||||
class FrameSettingsComponent : public juce::GroupComponent, public juce::AudioProcessorParameter::Listener, juce::AsyncUpdater {
|
||||
|
@ -25,14 +26,14 @@ private:
|
|||
bool animated = true;
|
||||
bool image = true;
|
||||
|
||||
juce::ToggleButton animate{"Animate"};
|
||||
juce::ToggleButton sync{"BPM Sync"};
|
||||
jux::SwitchButton animate{audioProcessor.animateFrames};
|
||||
jux::SwitchButton sync{audioProcessor.animationSyncBPM};
|
||||
juce::Label rateLabel{ "Framerate","Framerate"};
|
||||
juce::Label offsetLabel{ "Offset","Offset" };
|
||||
DoubleTextBox rateBox{ audioProcessor.animationRate->min, audioProcessor.animationRate->max };
|
||||
DoubleTextBox offsetBox{ audioProcessor.animationOffset->min, audioProcessor.animationRate->max };
|
||||
|
||||
juce::ToggleButton invertImage{"Invert Image"};
|
||||
jux::SwitchButton invertImage{audioProcessor.invertImage};
|
||||
EffectComponent threshold{ audioProcessor, *audioProcessor.imageThreshold };
|
||||
EffectComponent stride{ audioProcessor, *audioProcessor.imageStride };
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
inputEnabled.onClick = [this] {
|
||||
audioProcessor.inputEnabled->setBoolValueNotifyingHost(!audioProcessor.inputEnabled->getBoolValue());
|
||||
};
|
||||
inputEnabled.setTooltip("Enable to use input audio, instead of the generated audio.");
|
||||
|
||||
addAndMakeVisible(fileLabel);
|
||||
fileLabel.setJustificationType(juce::Justification::centred);
|
||||
|
|
|
@ -5,20 +5,10 @@ MidiComponent::MidiComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
setText("MIDI Settings");
|
||||
|
||||
addAndMakeVisible(midiToggle);
|
||||
addAndMakeVisible(midiLabel);
|
||||
addAndMakeVisible(voicesSlider);
|
||||
addAndMakeVisible(voicesLabel);
|
||||
addAndMakeVisible(keyboard);
|
||||
|
||||
midiToggle.setToggleState(audioProcessor.midiEnabled->getBoolValue(), juce::dontSendNotification);
|
||||
midiToggle.setTooltip("Enable MIDI input for the synth. If disabled, the synth will play a constant tone, as controlled by the frequency slider.");
|
||||
|
||||
midiToggle.onClick = [this]() {
|
||||
audioProcessor.midiEnabled->setBoolValueNotifyingHost(midiToggle.getToggleState());
|
||||
};
|
||||
|
||||
audioProcessor.midiEnabled->addListener(this);
|
||||
|
||||
voicesSlider.setRange(1, 16, 1);
|
||||
voicesSlider.setValue(audioProcessor.voices->getValueUnnormalised(), juce::dontSendNotification);
|
||||
voicesSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 50, 20);
|
||||
|
@ -69,7 +59,6 @@ MidiComponent::~MidiComponent() {
|
|||
audioProcessor.releaseTime->removeListener(this);
|
||||
audioProcessor.releaseShape->removeListener(this);
|
||||
|
||||
audioProcessor.midiEnabled->removeListener(this);
|
||||
audioProcessor.voices->removeListener(this);
|
||||
}
|
||||
|
||||
|
@ -80,7 +69,6 @@ void MidiComponent::parameterValueChanged(int parameterIndex, float newValue) {
|
|||
void MidiComponent::parameterGestureChanged(int parameterIndex, bool gestureIsStarting) {}
|
||||
|
||||
void MidiComponent::handleAsyncUpdate() {
|
||||
midiToggle.setToggleState(audioProcessor.midiEnabled->getBoolValue(), juce::dontSendNotification);
|
||||
voicesSlider.setValue(audioProcessor.voices->getValueUnnormalised(), juce::dontSendNotification);
|
||||
|
||||
Env newEnv = Env(
|
||||
|
@ -110,9 +98,7 @@ void MidiComponent::handleAsyncUpdate() {
|
|||
void MidiComponent::resized() {
|
||||
auto area = getLocalBounds().withTrimmedTop(20).reduced(20);
|
||||
auto topRow = area.removeFromTop(30);
|
||||
auto midiToggleBounds = topRow.removeFromLeft(120);
|
||||
midiToggle.setBounds(midiToggleBounds.removeFromLeft(30).withSizeKeepingCentre(30, 20).translated(0, 1));
|
||||
midiLabel.setBounds(midiToggleBounds);
|
||||
midiToggle.setBounds(topRow.removeFromLeft(120).translated(0, 1));
|
||||
topRow.removeFromLeft(80);
|
||||
voicesSlider.setBounds(topRow.removeFromLeft(250));
|
||||
if (midiSettingsButton.isVisible()) {
|
||||
|
|
|
@ -20,8 +20,7 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
OscirenderAudioProcessorEditor& pluginEditor;
|
||||
|
||||
juce::Label midiLabel{"midiLabel", "MIDI Enabled"};
|
||||
jux::SwitchButton midiToggle = { "switchButton", false };
|
||||
jux::SwitchButton midiToggle = jux::SwitchButton(audioProcessor.midiEnabled);
|
||||
juce::Slider voicesSlider;
|
||||
juce::Label voicesLabel;
|
||||
juce::TextButton midiSettingsButton{"Audio/MIDI Settings..."};
|
||||
|
|
|
@ -67,7 +67,7 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
}
|
||||
|
||||
if (juce::JUCEApplicationBase::isStandaloneApp()) {
|
||||
if (juce::TopLevelWindow::getNumTopLevelWindows() == 1) {
|
||||
if (juce::TopLevelWindow::getNumTopLevelWindows() > 0) {
|
||||
juce::TopLevelWindow* w = juce::TopLevelWindow::getTopLevelWindow(0);
|
||||
juce::DocumentWindow* dw = dynamic_cast<juce::DocumentWindow*>(w);
|
||||
if (dw != nullptr) {
|
||||
|
|
|
@ -149,6 +149,9 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
permanentEffects.push_back(thresholdEffect);
|
||||
permanentEffects.push_back(imageThreshold);
|
||||
permanentEffects.push_back(imageStride);
|
||||
permanentEffects.push_back(intensityEffect);
|
||||
permanentEffects.push_back(persistenceEffect);
|
||||
permanentEffects.push_back(hueEffect);
|
||||
|
||||
for (int i = 0; i < 26; i++) {
|
||||
addLuaSlider();
|
||||
|
@ -157,9 +160,6 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
allEffects = toggleableEffects;
|
||||
allEffects.insert(allEffects.end(), permanentEffects.begin(), permanentEffects.end());
|
||||
allEffects.insert(allEffects.end(), luaEffects.begin(), luaEffects.end());
|
||||
allEffects.push_back(intensityEffect);
|
||||
allEffects.push_back(persistenceEffect);
|
||||
allEffects.push_back(hueEffect);
|
||||
|
||||
for (auto effect : allEffects) {
|
||||
for (auto effectParameter : effect->parameters) {
|
||||
|
|
|
@ -184,8 +184,8 @@ public:
|
|||
)
|
||||
);
|
||||
|
||||
BooleanParameter* midiEnabled = new BooleanParameter("MIDI Enabled", "midiEnabled", VERSION_HINT, false);
|
||||
BooleanParameter* inputEnabled = new BooleanParameter("Audio Input Enabled", "inputEnabled", VERSION_HINT, false);
|
||||
BooleanParameter* midiEnabled = new BooleanParameter("MIDI Enabled", "midiEnabled", VERSION_HINT, false, "Enable MIDI input for the synth. If disabled, the synth will play a constant tone, as controlled by the frequency slider.");
|
||||
BooleanParameter* inputEnabled = new BooleanParameter("Audio Input Enabled", "inputEnabled", VERSION_HINT, false, "Enable to use input audio, instead of the generated audio.");
|
||||
std::atomic<float> frequency = 220.0f;
|
||||
|
||||
juce::SpinLock parsersLock;
|
||||
|
@ -223,12 +223,12 @@ public:
|
|||
|
||||
IntParameter* voices = new IntParameter("Voices", "voices", VERSION_HINT, 4, 1, 16);
|
||||
|
||||
BooleanParameter* animateFrames = new BooleanParameter("Animate", "animateFrames", VERSION_HINT, true);
|
||||
BooleanParameter* animationSyncBPM = new BooleanParameter("Sync To BPM", "animationSyncBPM", VERSION_HINT, false);
|
||||
BooleanParameter* animateFrames = new BooleanParameter("Animate", "animateFrames", VERSION_HINT, true, "Enables animation for files that have multiple frames, such as GIFs or Line Art.");
|
||||
BooleanParameter* animationSyncBPM = new BooleanParameter("Sync To BPM", "animationSyncBPM", VERSION_HINT, false, "Synchronises the animation's framerate with the BPM of your DAW.");
|
||||
FloatParameter* animationRate = new FloatParameter("Animation Rate", "animationRate", VERSION_HINT, 30, -1000, 1000, 0.01);
|
||||
FloatParameter* animationOffset = new FloatParameter("Animation Offset", "animationOffset", VERSION_HINT, 0, -10000, 10000, 0.1);
|
||||
|
||||
BooleanParameter* invertImage = new BooleanParameter("Invert Image", "invertImage", VERSION_HINT, false);
|
||||
BooleanParameter* invertImage = new BooleanParameter("Invert Image", "invertImage", VERSION_HINT, false, "Inverts the image so that dark pixels become light, and vice versa.");
|
||||
std::shared_ptr<Effect> imageThreshold = std::make_shared<Effect>(
|
||||
[this](int index, Point input, const std::vector<double>& values, double sampleRate) {
|
||||
return input;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
class BooleanParameter : public juce::AudioProcessorParameterWithID {
|
||||
public:
|
||||
BooleanParameter(juce::String name, juce::String id, int versionHint, bool value) : AudioProcessorParameterWithID(juce::ParameterID(id, versionHint), name), value(value) {}
|
||||
BooleanParameter(juce::String name, juce::String id, int versionHint, bool value, juce::String description) : AudioProcessorParameterWithID(juce::ParameterID(id, versionHint), name), value(value), description(description) {}
|
||||
|
||||
juce::String getName(int maximumStringLength) const override {
|
||||
return name.substring(0, maximumStringLength);
|
||||
|
@ -83,7 +83,12 @@ public:
|
|||
void load(juce::XmlElement* xml) {
|
||||
setBoolValueNotifyingHost(xml->getBoolAttribute("value", getDefaultValue()));
|
||||
}
|
||||
|
||||
juce::String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> value = false;
|
||||
juce::String description;
|
||||
};
|
||||
|
|
|
@ -167,7 +167,7 @@ void Effect::markEnableable(bool enable) {
|
|||
if (enabled != nullptr) {
|
||||
enabled->setValue(enable);
|
||||
} else {
|
||||
enabled = new BooleanParameter(getName() + " Enabled", getId() + "Enabled", parameters[0]->getVersionHint(), enable);
|
||||
enabled = new BooleanParameter(getName() + " Enabled", getId() + "Enabled", parameters[0]->getVersionHint(), enable, "Toggles the effect.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -329,7 +329,7 @@ public:
|
|||
std::atomic<bool> smoothValueChange = true;
|
||||
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", getVersionHint(), 1);
|
||||
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 1000.0f, 0.01f, "Hz");
|
||||
BooleanParameter* sidechain = new BooleanParameter(name + " Sidechain Enabled", paramID + "Sidechain", getVersionHint(), false);
|
||||
BooleanParameter* sidechain = new BooleanParameter(name + " Sidechain Enabled", paramID + "Sidechain", getVersionHint(), false, "Toggles " + name + " Sidechain.");
|
||||
std::atomic<float> phase = 0.0f;
|
||||
juce::String description;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, in
|
|||
menu.addCustomItem(2, min, 160, 40, false);
|
||||
menu.addCustomItem(3, max, 160, 40, false);
|
||||
|
||||
menu.showMenuAsync(juce::PopupMenu::Options().withParentComponent(audioProcessor.getActiveEditor()), [this](int result) {});
|
||||
menu.showMenuAsync(juce::PopupMenu::Options(), [this](int result) {});
|
||||
};
|
||||
|
||||
effect.addListener(index, this);
|
||||
|
|
|
@ -34,6 +34,7 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
|
|||
if (toggle != nullptr) {
|
||||
toggle->addListener(this);
|
||||
setToggleState(toggle->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||
setTooltip(toggle->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "JuceHeader.h"
|
||||
#include "../audio/BooleanParameter.h"
|
||||
|
||||
namespace jux
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ namespace jux
|
|||
@see juce::ToggableButton
|
||||
|
||||
*/
|
||||
class SwitchButton : public juce::Button
|
||||
class SwitchButton : public juce::Button, public juce::AudioProcessorParameter::Listener
|
||||
{
|
||||
public:
|
||||
enum ColourIds
|
||||
|
@ -56,6 +57,32 @@ public:
|
|||
switchCircle.setWantsKeyboardFocus (false);
|
||||
switchCircle.setInterceptsMouseClicks (false, false);
|
||||
}
|
||||
|
||||
SwitchButton(BooleanParameter* parameter) : SwitchButton(parameter->name, false) {
|
||||
this->parameter = parameter;
|
||||
setToggleState(parameter->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||
parameter->addListener(this);
|
||||
onStateChange = [this]() {
|
||||
this->parameter->setBoolValueNotifyingHost(getToggleState());
|
||||
};
|
||||
addAndMakeVisible(label);
|
||||
label.setTooltip(parameter->getDescription());
|
||||
label.setText(parameter->name, juce::NotificationType::dontSendNotification);
|
||||
}
|
||||
|
||||
~SwitchButton() {
|
||||
if (parameter != nullptr) {
|
||||
parameter->removeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
void parameterValueChanged(int parameterIndex, float newValue) override {
|
||||
juce::MessageManager::callAsync([this]() {
|
||||
setToggleState(parameter->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||
});
|
||||
}
|
||||
|
||||
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override {}
|
||||
|
||||
void setMillisecondsToSpendMoving (int newValue)
|
||||
{
|
||||
|
@ -98,8 +125,10 @@ public:
|
|||
{
|
||||
Button::resized();
|
||||
auto b = getSwitchBounds();
|
||||
label.setBounds(getLabelBounds());
|
||||
|
||||
juce::Rectangle<float> switchCircleBounds;
|
||||
if (! isVertical)
|
||||
if (!isVertical)
|
||||
switchCircleBounds = { getSwitchState() ? b.getRight() - b.getHeight() : b.getX(), b.getY(), b.getHeight(), b.getHeight() };
|
||||
else
|
||||
switchCircleBounds = {
|
||||
|
@ -113,6 +142,7 @@ public:
|
|||
|
||||
private:
|
||||
int millisecondsToSpendMoving { 75 };
|
||||
juce::Label label;
|
||||
|
||||
bool getSwitchState() const
|
||||
{
|
||||
|
@ -121,13 +151,16 @@ private:
|
|||
bool isInverted = false;
|
||||
bool isVertical = false;
|
||||
|
||||
juce::Rectangle<float> getSwitchBounds()
|
||||
{
|
||||
auto b = getLocalBounds().toFloat().reduced(4, 4).translated(0, -1);
|
||||
return b;
|
||||
juce::Rectangle<float> getSwitchBounds() {
|
||||
return getLocalBounds().removeFromLeft(30).withSizeKeepingCentre(30, 20).toFloat().reduced(4, 4).translated(0, -1);
|
||||
}
|
||||
|
||||
juce::Rectangle<int> getLabelBounds() {
|
||||
auto b = getLocalBounds();
|
||||
b.removeFromLeft(34);
|
||||
return b.translated(0, -1);
|
||||
}
|
||||
|
||||
juce::String onText, offText;
|
||||
class SwitchCircle : public Component
|
||||
{
|
||||
void paint (juce::Graphics& g) override
|
||||
|
@ -139,6 +172,8 @@ private:
|
|||
juce::ComponentAnimator animator;
|
||||
|
||||
bool prevToggleState = false;
|
||||
|
||||
BooleanParameter* parameter = nullptr;
|
||||
};
|
||||
|
||||
} // namespace jux
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
#include "VisualiserComponent.h"
|
||||
#include "../LookAndFeel.h"
|
||||
#include "VisualiserSettings.h"
|
||||
#include "VisualiserComponent.h"
|
||||
|
||||
VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, VisualiserComponent* parent, bool useOldVisualiser) : backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), oldVisualiser(useOldVisualiser), juce::Thread("VisualiserComponent"), parent(parent) {
|
||||
resetBuffer();
|
||||
startTimerHz(60);
|
||||
startThread();
|
||||
|
||||
settingsWindow.setResizable(false, false);
|
||||
settingsWindow.setUsingNativeTitleBar(true);
|
||||
settings.setLookAndFeel(&getLookAndFeel());
|
||||
settings.setSize(550, 130);
|
||||
settingsWindow.setContentNonOwned(&settings, true);
|
||||
|
||||
setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
||||
setWantsKeyboardFocus(true);
|
||||
|
||||
|
@ -282,29 +287,7 @@ void VisualiserComponent::popoutWindow() {
|
|||
popOutButton.setVisible(false);
|
||||
}
|
||||
|
||||
void VisualiserComponent::setIntensity(double intensity) {
|
||||
browser.emitEventIfBrowserIsVisible("intensityChanged", intensity);
|
||||
}
|
||||
|
||||
void VisualiserComponent::setPersistence(double persistence) {
|
||||
browser.emitEventIfBrowserIsVisible("persistenceChanged", persistence);
|
||||
}
|
||||
|
||||
void VisualiserComponent::setHue(double hue) {
|
||||
browser.emitEventIfBrowserIsVisible("hueChanged", hue);
|
||||
}
|
||||
|
||||
void VisualiserComponent::openSettings() {
|
||||
juce::DialogWindow::LaunchOptions options;
|
||||
VisualiserSettings* settings = new VisualiserSettings(audioProcessor, *this);
|
||||
settings->setLookAndFeel(&getLookAndFeel());
|
||||
options.content.setOwned(settings);
|
||||
options.content->setSize(500, 250);
|
||||
options.dialogTitle = "Visualiser Settings";
|
||||
options.dialogBackgroundColour = Colours::dark;
|
||||
options.escapeKeyTriggersCloseButton = true;
|
||||
options.useNativeTitleBar = true;
|
||||
options.resizable = false;
|
||||
|
||||
juce::DialogWindow* dw = options.launchAsync();
|
||||
settingsWindow.setVisible(true);
|
||||
settingsWindow.toFront(true);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <JuceHeader.h>
|
||||
#include "../LookAndFeel.h"
|
||||
#include "../concurrency/BufferConsumer.h"
|
||||
#include "../PluginProcessor.h"
|
||||
#include "LabelledTextBox.h"
|
||||
#include "SvgButton.h"
|
||||
#include "VisualiserSettings.h"
|
||||
|
||||
enum class FullScreenMode {
|
||||
TOGGLE,
|
||||
|
@ -121,6 +123,9 @@ private:
|
|||
.withNativeFunction("pause", [this](auto& var, auto complete) {
|
||||
setPaused(active);
|
||||
})
|
||||
.withNativeFunction("getSettings", [this](auto& var, auto complete) {
|
||||
complete(settings.getSettings());
|
||||
})
|
||||
);
|
||||
|
||||
std::vector<float> tempBuffer;
|
||||
|
@ -129,6 +134,8 @@ private:
|
|||
std::shared_ptr<BufferConsumer> consumer;
|
||||
|
||||
std::function<void(FullScreenMode)> fullScreenCallback;
|
||||
VisualiserSettings settings = VisualiserSettings(audioProcessor, *this);
|
||||
SettingsWindow settingsWindow = SettingsWindow("Visualiser Settings");
|
||||
|
||||
void resetBuffer();
|
||||
void popoutWindow();
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
#include "VisualiserSettings.h"
|
||||
#include "VisualiserComponent.h"
|
||||
#include "../PluginEditor.h"
|
||||
|
||||
VisualiserSettings::VisualiserSettings(OscirenderAudioProcessor& p, VisualiserComponent& visualiser) : audioProcessor(p), visualiser(visualiser) {
|
||||
addAndMakeVisible(intensity);
|
||||
addAndMakeVisible(persistence);
|
||||
addAndMakeVisible(hue);
|
||||
|
||||
intensity.slider.onValueChange = [this] {
|
||||
double value = intensity.slider.getValue();
|
||||
intensity.effect.setValue(value);
|
||||
this->visualiser.setIntensity(value);
|
||||
};
|
||||
persistence.slider.onValueChange = [this] {
|
||||
double value = persistence.slider.getValue();
|
||||
persistence.effect.setValue(value);
|
||||
this->visualiser.setPersistence(value);
|
||||
};
|
||||
hue.slider.onValueChange = [this] {
|
||||
double value = hue.slider.getValue();
|
||||
hue.effect.setValue(value);
|
||||
this->visualiser.setHue(value);
|
||||
|
||||
intensity.setSliderOnValueChange();
|
||||
persistence.setSliderOnValueChange();
|
||||
hue.setSliderOnValueChange();
|
||||
|
||||
gridToggle.setToggleState(audioProcessor.midiEnabled->getBoolValue(), juce::dontSendNotification);
|
||||
gridToggle.setTooltip("Enables the oscilloscope graticule.");
|
||||
|
||||
gridToggle.onClick = [this]() {
|
||||
audioProcessor.midiEnabled->setBoolValueNotifyingHost(gridToggle.getToggleState());
|
||||
};
|
||||
}
|
||||
|
||||
VisualiserSettings::~VisualiserSettings() {}
|
||||
|
||||
void VisualiserSettings::resized() {
|
||||
auto area = getLocalBounds().withTrimmedTop(20).reduced(20);
|
||||
auto area = getLocalBounds().reduced(20);
|
||||
double rowHeight = 30;
|
||||
intensity.setBounds(area.removeFromTop(rowHeight));
|
||||
persistence.setBounds(area.removeFromTop(rowHeight));
|
||||
hue.setBounds(area.removeFromTop(rowHeight));
|
||||
}
|
||||
|
||||
juce::var VisualiserSettings::getSettings() {
|
||||
auto settings = new juce::DynamicObject();
|
||||
settings->setProperty("intensity", audioProcessor.intensityEffect->getActualValue());
|
||||
settings->setProperty("persistence", audioProcessor.persistenceEffect->getActualValue());
|
||||
settings->setProperty("hue", audioProcessor.hueEffect->getActualValue());
|
||||
return juce::var(settings);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "VisualiserComponent.h"
|
||||
#include "EffectComponent.h"
|
||||
#include "SvgButton.h"
|
||||
#include "../LookAndFeel.h"
|
||||
#include "SwitchButton.h"
|
||||
|
||||
class VisualiserComponent;
|
||||
class VisualiserSettings : public juce::Component {
|
||||
public:
|
||||
VisualiserSettings(OscirenderAudioProcessor&, VisualiserComponent&);
|
||||
~VisualiserSettings();
|
||||
|
||||
void resized() override;
|
||||
juce::var getSettings();
|
||||
private:
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
VisualiserComponent& visualiser;
|
||||
|
@ -18,6 +21,18 @@ private:
|
|||
EffectComponent intensity{audioProcessor, *audioProcessor.intensityEffect};
|
||||
EffectComponent persistence{audioProcessor, *audioProcessor.persistenceEffect};
|
||||
EffectComponent hue{audioProcessor, *audioProcessor.hueEffect};
|
||||
|
||||
jux::SwitchButton gridToggle = { "gridToggle", false };
|
||||
jux::SwitchButton noiseToggle = { "noiseToggle", false };
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserSettings)
|
||||
};
|
||||
|
||||
class SettingsWindow : public juce::DocumentWindow {
|
||||
public:
|
||||
SettingsWindow(juce::String name) : juce::DocumentWindow(name, Colours::darker, juce::DocumentWindow::TitleBarButtons::closeButton) {}
|
||||
|
||||
void closeButtonPressed() override {
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue