kopia lustrzana https://github.com/jameshball/osci-render
Add fixed rotate buttons to perspective effect
rodzic
90ce1a73a2
commit
3a50b4f53e
|
@ -25,9 +25,9 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
|
||||||
audioProcessor.rotateY->setValue(rotateY.slider.getValue());
|
audioProcessor.rotateY->setValue(rotateY.slider.getValue());
|
||||||
audioProcessor.rotateZ->setValue(rotateZ.slider.getValue());
|
audioProcessor.rotateZ->setValue(rotateZ.slider.getValue());
|
||||||
|
|
||||||
audioProcessor.fixedRotateX = fixedRotateX->getToggleState();
|
audioProcessor.fixedRotateX->setBoolValueNotifyingHost(fixedRotateX->getToggleState());
|
||||||
audioProcessor.fixedRotateY = fixedRotateY->getToggleState();
|
audioProcessor.fixedRotateY->setBoolValueNotifyingHost(fixedRotateY->getToggleState());
|
||||||
audioProcessor.fixedRotateZ = fixedRotateZ->getToggleState();
|
audioProcessor.fixedRotateZ->setBoolValueNotifyingHost(fixedRotateZ->getToggleState());
|
||||||
};
|
};
|
||||||
|
|
||||||
rotateX.slider.onValueChange = onRotationChange;
|
rotateX.slider.onValueChange = onRotationChange;
|
||||||
|
@ -73,10 +73,6 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
|
||||||
rotateX.setComponent(fixedRotateX);
|
rotateX.setComponent(fixedRotateX);
|
||||||
rotateY.setComponent(fixedRotateY);
|
rotateY.setComponent(fixedRotateY);
|
||||||
rotateZ.setComponent(fixedRotateZ);
|
rotateZ.setComponent(fixedRotateZ);
|
||||||
|
|
||||||
fixedRotateX->setToggleState(audioProcessor.fixedRotateX, juce::NotificationType::dontSendNotification);
|
|
||||||
fixedRotateY->setToggleState(audioProcessor.fixedRotateY, juce::NotificationType::dontSendNotification);
|
|
||||||
fixedRotateZ->setToggleState(audioProcessor.fixedRotateZ, juce::NotificationType::dontSendNotification);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjComponent::~ObjComponent() {
|
ObjComponent::~ObjComponent() {
|
||||||
|
|
|
@ -27,9 +27,9 @@ private:
|
||||||
juce::TextButton resetRotation{"Reset Rotation"};
|
juce::TextButton resetRotation{"Reset Rotation"};
|
||||||
juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"};
|
juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"};
|
||||||
|
|
||||||
std::shared_ptr<SvgButton> fixedRotateX = std::make_shared<SvgButton>("fixedRotateX", juce::String(BinaryData::fixed_rotate_svg), "white", "red");
|
std::shared_ptr<SvgButton> fixedRotateX = std::make_shared<SvgButton>("fixedRotateX", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateX);
|
||||||
std::shared_ptr<SvgButton> fixedRotateY = std::make_shared<SvgButton>("fixedRotateY", juce::String(BinaryData::fixed_rotate_svg), "white", "red");
|
std::shared_ptr<SvgButton> fixedRotateY = std::make_shared<SvgButton>("fixedRotateY", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateY);
|
||||||
std::shared_ptr<SvgButton> fixedRotateZ = std::make_shared<SvgButton>("fixedRotateZ", juce::String(BinaryData::fixed_rotate_svg), "white", "red");
|
std::shared_ptr<SvgButton> fixedRotateZ = std::make_shared<SvgButton>("fixedRotateZ", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateZ);
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ObjComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ObjComponent)
|
||||||
};
|
};
|
|
@ -124,6 +124,13 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addParameter(fixedRotateX);
|
||||||
|
addParameter(fixedRotateY);
|
||||||
|
addParameter(fixedRotateZ);
|
||||||
|
addParameter(perspectiveEffect->fixedRotateX);
|
||||||
|
addParameter(perspectiveEffect->fixedRotateY);
|
||||||
|
addParameter(perspectiveEffect->fixedRotateZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
|
||||||
|
|
|
@ -107,16 +107,16 @@ public:
|
||||||
}, new EffectParameter("Focal length", "focalLength", 1.0, 0.0, 2.0)
|
}, new EffectParameter("Focal length", "focalLength", 1.0, 0.0, 2.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
std::atomic<bool> fixedRotateX = false;
|
BooleanParameter* fixedRotateX = new BooleanParameter("Object Fixed Rotate X", "objFixedRotateX", false);
|
||||||
std::atomic<bool> fixedRotateY = false;
|
BooleanParameter* fixedRotateY = new BooleanParameter("Object Fixed Rotate Y", "objFixedRotateY", false);
|
||||||
std::atomic<bool> fixedRotateZ = false;
|
BooleanParameter* fixedRotateZ = new BooleanParameter("Object Fixed Rotate Z", "objFixedRotateZ", false);
|
||||||
std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
|
std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
|
||||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||||
if (getCurrentFileIndex() != -1) {
|
if (getCurrentFileIndex() != -1) {
|
||||||
auto obj = getCurrentFileParser()->getObject();
|
auto obj = getCurrentFileParser()->getObject();
|
||||||
if (obj == nullptr) return input;
|
if (obj == nullptr) return input;
|
||||||
auto rotation = values[0] * std::numbers::pi;
|
auto rotation = values[0] * std::numbers::pi;
|
||||||
if (fixedRotateX) {
|
if (fixedRotateX->getBoolValue()) {
|
||||||
obj->setCurrentRotationX(rotation);
|
obj->setCurrentRotationX(rotation);
|
||||||
} else {
|
} else {
|
||||||
obj->setBaseRotationX(rotation);
|
obj->setBaseRotationX(rotation);
|
||||||
|
@ -131,7 +131,7 @@ public:
|
||||||
auto obj = getCurrentFileParser()->getObject();
|
auto obj = getCurrentFileParser()->getObject();
|
||||||
if (obj == nullptr) return input;
|
if (obj == nullptr) return input;
|
||||||
auto rotation = values[0] * std::numbers::pi;
|
auto rotation = values[0] * std::numbers::pi;
|
||||||
if (fixedRotateY) {
|
if (fixedRotateY->getBoolValue()) {
|
||||||
obj->setCurrentRotationY(rotation);
|
obj->setCurrentRotationY(rotation);
|
||||||
} else {
|
} else {
|
||||||
obj->setBaseRotationY(rotation);
|
obj->setBaseRotationY(rotation);
|
||||||
|
@ -146,7 +146,7 @@ public:
|
||||||
auto obj = getCurrentFileParser()->getObject();
|
auto obj = getCurrentFileParser()->getObject();
|
||||||
if (obj == nullptr) return input;
|
if (obj == nullptr) return input;
|
||||||
auto rotation = values[0] * std::numbers::pi;
|
auto rotation = values[0] * std::numbers::pi;
|
||||||
if (fixedRotateZ) {
|
if (fixedRotateZ->getBoolValue()) {
|
||||||
obj->setCurrentRotationZ(rotation);
|
obj->setCurrentRotationZ(rotation);
|
||||||
} else {
|
} else {
|
||||||
obj->setBaseRotationZ(rotation);
|
obj->setBaseRotationZ(rotation);
|
||||||
|
|
|
@ -29,10 +29,22 @@ public:
|
||||||
return value.load();
|
return value.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getBoolValue() const {
|
||||||
|
return value.load();
|
||||||
|
}
|
||||||
|
|
||||||
void setValue(float newValue) override {
|
void setValue(float newValue) override {
|
||||||
value.store(newValue >= 0.5f);
|
value.store(newValue >= 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setBoolValue(bool newValue) {
|
||||||
|
value.store(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBoolValueNotifyingHost(bool newValue) {
|
||||||
|
setValueNotifyingHost(newValue ? 1.0f : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
float getDefaultValue() const override {
|
float getDefaultValue() const override {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,37 +7,55 @@ Vector2 PerspectiveEffect::apply(int index, Vector2 input, const std::vector<dou
|
||||||
auto effectScale = values[0];
|
auto effectScale = values[0];
|
||||||
auto depth = 1.0 + (values[1] - 0.1) * 3;
|
auto depth = 1.0 + (values[1] - 0.1) * 3;
|
||||||
auto rotateSpeed = linearSpeedToActualSpeed(values[2]);
|
auto rotateSpeed = linearSpeedToActualSpeed(values[2]);
|
||||||
auto baseRotateX = values[3] * std::numbers::pi;
|
double baseRotateX, baseRotateY, baseRotateZ;
|
||||||
auto baseRotateY = values[4] * std::numbers::pi;
|
if (fixedRotateX->getBoolValue()) {
|
||||||
auto baseRotateZ = values[5] * std::numbers::pi;
|
baseRotateX = 0;
|
||||||
|
currentRotateX = values[3] * std::numbers::pi;
|
||||||
|
} else {
|
||||||
|
baseRotateX = values[3] * std::numbers::pi;
|
||||||
|
}
|
||||||
|
if (fixedRotateY->getBoolValue()) {
|
||||||
|
baseRotateY = 0;
|
||||||
|
currentRotateY = values[4] * std::numbers::pi;
|
||||||
|
} else {
|
||||||
|
baseRotateY = values[4] * std::numbers::pi;
|
||||||
|
}
|
||||||
|
if (fixedRotateZ->getBoolValue()) {
|
||||||
|
baseRotateZ = 0;
|
||||||
|
currentRotateZ = values[5] * std::numbers::pi;
|
||||||
|
} else {
|
||||||
|
baseRotateZ = values[5] * std::numbers::pi;
|
||||||
|
}
|
||||||
|
|
||||||
currentRotateX += baseRotateX * rotateSpeed;
|
currentRotateX += baseRotateX * rotateSpeed;
|
||||||
currentRotateY += baseRotateY * rotateSpeed;
|
currentRotateY += baseRotateY * rotateSpeed;
|
||||||
currentRotateZ += baseRotateZ * rotateSpeed;
|
currentRotateZ += baseRotateZ * rotateSpeed;
|
||||||
|
|
||||||
if (currentRotateX > std::numbers::pi * 50) {
|
if (currentRotateX > std::numbers::pi * 8) {
|
||||||
currentRotateX -= std::numbers::pi * 50;
|
currentRotateX -= std::numbers::pi * 8;
|
||||||
}
|
}
|
||||||
if (currentRotateY > std::numbers::pi * 50) {
|
if (currentRotateY > std::numbers::pi * 8) {
|
||||||
currentRotateY -= std::numbers::pi * 50;
|
currentRotateY -= std::numbers::pi * 8;
|
||||||
}
|
}
|
||||||
if (currentRotateZ > std::numbers::pi * 50) {
|
if (currentRotateZ > std::numbers::pi * 8) {
|
||||||
currentRotateZ -= std::numbers::pi * 50;
|
currentRotateZ -= std::numbers::pi * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto x = input.x;
|
auto x = input.x;
|
||||||
auto y = input.y;
|
auto y = input.y;
|
||||||
auto z = 0.0;
|
auto z = 0.0;
|
||||||
|
|
||||||
parser.setVariable("x", x);
|
if (!defaultScript) {
|
||||||
parser.setVariable("y", y);
|
parser.setVariable("x", x);
|
||||||
parser.setVariable("z", z);
|
parser.setVariable("y", y);
|
||||||
|
parser.setVariable("z", z);
|
||||||
|
|
||||||
auto result = parser.run();
|
auto result = parser.run();
|
||||||
if (result.size() >= 3) {
|
if (result.size() >= 3) {
|
||||||
x = result[0];
|
x = result[0];
|
||||||
y = result[1];
|
y = result[1];
|
||||||
z = result[2];
|
z = result[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rotateX = baseRotateX + currentRotateX;
|
auto rotateX = baseRotateX + currentRotateX;
|
||||||
|
|
|
@ -9,10 +9,15 @@ public:
|
||||||
PerspectiveEffect();
|
PerspectiveEffect();
|
||||||
|
|
||||||
Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
|
Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
|
||||||
|
|
||||||
|
BooleanParameter* fixedRotateX = new BooleanParameter("Perspective Fixed Rotate X", "perspectiveFixedRotateX", false);
|
||||||
|
BooleanParameter* fixedRotateY = new BooleanParameter("Perspective Fixed Rotate Y", "perspectiveFixedRotateY", false);
|
||||||
|
BooleanParameter* fixedRotateZ = new BooleanParameter("Perspective Fixed Rotate Z", "perspectiveFixedRotateZ", false);
|
||||||
private:
|
private:
|
||||||
const juce::String DEFAULT_SCRIPT = "return { x, y, z }";
|
const juce::String DEFAULT_SCRIPT = "return { x, y, z }";
|
||||||
juce::MemoryBlock code{DEFAULT_SCRIPT.toRawUTF8(), DEFAULT_SCRIPT.getNumBytesAsUTF8() + 1};
|
juce::MemoryBlock code{DEFAULT_SCRIPT.toRawUTF8(), DEFAULT_SCRIPT.getNumBytesAsUTF8() + 1};
|
||||||
LuaParser parser{DEFAULT_SCRIPT};
|
LuaParser parser{DEFAULT_SCRIPT};
|
||||||
|
bool defaultScript = true;
|
||||||
|
|
||||||
float currentRotateX = 0;
|
float currentRotateX = 0;
|
||||||
float currentRotateY = 0;
|
float currentRotateY = 0;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#include "EffectsListComponent.h"
|
#include "EffectsListComponent.h"
|
||||||
|
#include "SvgButton.h"
|
||||||
|
|
||||||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, Effect& effect) : DraggableListBoxItem(lb, data, rn), effect(effect), audioProcessor(data.audioProcessor) {
|
||||||
auto parameters = effect->parameters;
|
auto parameters = effect.parameters;
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(data.audioProcessor, *effect, i, i == 0);
|
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(audioProcessor, effect, i, i == 0);
|
||||||
// using weak_ptr to avoid circular reference and memory leak
|
// using weak_ptr to avoid circular reference and memory leak
|
||||||
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
||||||
effectComponent->slider.setValue(parameters[i]->getValueUnnormalised(), juce::dontSendNotification);
|
effectComponent->slider.setValue(parameters[i]->getValueUnnormalised(), juce::dontSendNotification);
|
||||||
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
|
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
|
||||||
if (auto effectComponent = weakEffectComponent.lock()) {
|
if (auto effectComponent = weakEffectComponent.lock()) {
|
||||||
this->effect->setValue(i, effectComponent->slider.getValue());
|
this->effect.setValue(i, effectComponent->slider.getValue());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,12 +18,17 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
||||||
effectComponent->selected.onClick = [this, weakEffectComponent] {
|
effectComponent->selected.onClick = [this, weakEffectComponent] {
|
||||||
if (auto effectComponent = weakEffectComponent.lock()) {
|
if (auto effectComponent = weakEffectComponent.lock()) {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||||
data.setSelected(rowNum, effectComponent->selected.getToggleState());
|
data.setSelected(rowNum, effectComponent->selected.getToggleState());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto component = createComponent(parameters[i]);
|
||||||
|
if (component != nullptr) {
|
||||||
|
effectComponent->setComponent(component);
|
||||||
|
}
|
||||||
|
|
||||||
listModel.addComponent(effectComponent);
|
listModel.addComponent(effectComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +72,25 @@ void EffectsListComponent::resized() {
|
||||||
list.setBounds(area);
|
list.setBounds(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectParameter* parameter) {
|
||||||
|
if (parameter->paramID == "rotateX" || parameter->paramID == "rotateY" || parameter->paramID == "rotateZ") {
|
||||||
|
BooleanParameter* toggle;
|
||||||
|
if (parameter->paramID == "rotateX") {
|
||||||
|
toggle = audioProcessor.perspectiveEffect->fixedRotateX;
|
||||||
|
} else if (parameter->paramID == "rotateY") {
|
||||||
|
toggle = audioProcessor.perspectiveEffect->fixedRotateY;
|
||||||
|
} else if (parameter->paramID == "rotateZ") {
|
||||||
|
toggle = audioProcessor.perspectiveEffect->fixedRotateZ;
|
||||||
|
}
|
||||||
|
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, "white", "red", toggle);
|
||||||
|
button->onClick = [this, toggle] {
|
||||||
|
toggle->setBoolValueNotifyingHost(!toggle->getBoolValue());
|
||||||
|
};
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int EffectsListBoxModel::getRowHeight(int row) {
|
int EffectsListBoxModel::getRowHeight(int row) {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
return data.getEffect(row)->parameters.size() * 30;
|
return data.getEffect(row)->parameters.size() * 30;
|
||||||
|
@ -79,7 +104,7 @@ juce::Component* EffectsListBoxModel::refreshComponentForRow(int rowNumber, bool
|
||||||
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
||||||
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, data.getEffect(rowNumber));
|
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, *data.getEffect(rowNumber));
|
||||||
}
|
}
|
||||||
return item.release();
|
return item.release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
class EffectsListComponent : public DraggableListBoxItem
|
class EffectsListComponent : public DraggableListBoxItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect);
|
EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, Effect& effect);
|
||||||
~EffectsListComponent();
|
~EffectsListComponent();
|
||||||
|
|
||||||
void paint(juce::Graphics& g) override;
|
void paint(juce::Graphics& g) override;
|
||||||
|
@ -97,10 +97,14 @@ public:
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Effect> effect;
|
Effect& effect;
|
||||||
ComponentListModel listModel;
|
ComponentListModel listModel;
|
||||||
juce::ListBox list;
|
juce::ListBox list;
|
||||||
private:
|
private:
|
||||||
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
|
||||||
|
std::shared_ptr<juce::Component> createComponent(EffectParameter* parameter);
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
|
|
||||||
class SvgButton : public juce::DrawableButton {
|
class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParameter::Listener, public juce::AsyncUpdater {
|
||||||
public:
|
public:
|
||||||
SvgButton(juce::String name, juce::String svg, juce::String colour, juce::String colourOn) : juce::DrawableButton(name, juce::DrawableButton::ButtonStyle::ImageFitted) {
|
SvgButton(juce::String name, juce::String svg, juce::String colour, juce::String colourOn, BooleanParameter* toggle = nullptr) : juce::DrawableButton(name, juce::DrawableButton::ButtonStyle::ImageFitted), toggle(toggle) {
|
||||||
auto doc = juce::XmlDocument::parse(svg);
|
auto doc = juce::XmlDocument::parse(svg);
|
||||||
changeSvgColour(doc.get(), colour);
|
changeSvgColour(doc.get(), colour);
|
||||||
normalImage = juce::Drawable::createFromSVG(*doc);
|
normalImage = juce::Drawable::createFromSVG(*doc);
|
||||||
|
@ -16,14 +16,34 @@ class SvgButton : public juce::DrawableButton {
|
||||||
setClickingTogglesState(true);
|
setClickingTogglesState(true);
|
||||||
}
|
}
|
||||||
setImages(normalImage.get(), nullptr, nullptr, nullptr, normalImageOn.get());
|
setImages(normalImage.get(), nullptr, nullptr, nullptr, normalImageOn.get());
|
||||||
|
|
||||||
|
if (toggle != nullptr) {
|
||||||
|
toggle->addListener(this);
|
||||||
|
setToggleState(toggle->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SvgButton(juce::String name, juce::String svg, juce::String colour) : SvgButton(name, svg, colour, colour) {}
|
SvgButton(juce::String name, juce::String svg, juce::String colour) : SvgButton(name, svg, colour, colour) {}
|
||||||
|
|
||||||
~SvgButton() override {}
|
~SvgButton() override {
|
||||||
|
if (toggle != nullptr) {
|
||||||
|
toggle->removeListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parameterValueChanged(int parameterIndex, float newValue) override {
|
||||||
|
triggerAsyncUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override {}
|
||||||
|
|
||||||
|
void handleAsyncUpdate() override {
|
||||||
|
setToggleState(toggle->getBoolValue(), juce::NotificationType::dontSendNotification);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<juce::Drawable> normalImage;
|
std::unique_ptr<juce::Drawable> normalImage;
|
||||||
std::unique_ptr<juce::Drawable> normalImageOn;
|
std::unique_ptr<juce::Drawable> normalImageOn;
|
||||||
|
BooleanParameter* toggle;
|
||||||
|
|
||||||
void changeSvgColour(juce::XmlElement* xml, juce::String colour) {
|
void changeSvgColour(juce::XmlElement* xml, juce::String colour) {
|
||||||
forEachXmlChildElement(*xml, xmlnode) {
|
forEachXmlChildElement(*xml, xmlnode) {
|
||||||
|
|
|
@ -86,6 +86,6 @@ void VisualiserComponent::paintXY(juce::Graphics& g, juce::Rectangle<float> area
|
||||||
double strength = 10;
|
double strength = 10;
|
||||||
lengthScale = std::log(strength * lengthScale + 1) / std::log(strength + 1);
|
lengthScale = std::log(strength * lengthScale + 1) / std::log(strength + 1);
|
||||||
g.setColour(waveformColour.withAlpha(lengthScale));
|
g.setColour(waveformColour.withAlpha(lengthScale));
|
||||||
g.drawLine(line, 2.0f);
|
g.drawLine(line, area.getWidth() / 150.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue