Merge pull request #81 from jameshball/interface-refresh

Interface refresh
pull/170/head
James H Ball 2023-12-19 12:20:36 +00:00 zatwierdzone przez GitHub
commit 90fcd085be
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
20 zmienionych plików z 510 dodań i 302 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
#include "LookAndFeel.h"
OscirenderLookAndFeel::OscirenderLookAndFeel() {
// slider
setColour(juce::Slider::thumbColourId, Colours::veryDark);
setColour(juce::Slider::textBoxOutlineColourId, juce::Colours::white);
setColour(juce::Slider::textBoxBackgroundColourId, Colours::veryDark);
@ -8,38 +9,72 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() {
setColour(juce::Slider::trackColourId, juce::Colours::grey);
setColour(juce::Slider::backgroundColourId, Colours::dark);
setColour(sliderThumbOutlineColourId, juce::Colours::white);
// buttons
setColour(juce::ToggleButton::tickDisabledColourId, juce::Colours::white);
setColour(juce::ResizableWindow::backgroundColourId, Colours::dark);
setColour(juce::TextButton::buttonColourId, Colours::veryDark);
// windows & menus
setColour(juce::ResizableWindow::backgroundColourId, Colours::grey);
setColour(groupComponentBackgroundColourId, Colours::darker);
setColour(groupComponentHeaderColourId, Colours::veryDark);
setColour(juce::PopupMenu::backgroundColourId, Colours::veryDark);
setColour(juce::PopupMenu::highlightedBackgroundColourId, Colours::darker);
setColour(juce::TooltipWindow::backgroundColourId, Colours::veryDark);
setColour(juce::TooltipWindow::outlineColourId, juce::Colours::white);
// combo box
setColour(juce::ComboBox::backgroundColourId, Colours::veryDark);
setColour(juce::ComboBox::outlineColourId, juce::Colours::white);
setColour(juce::ComboBox::arrowColourId, juce::Colours::white);
setColour(juce::TextButton::buttonColourId, Colours::veryDark);
// text box
setColour(juce::TextEditor::backgroundColourId, Colours::veryDark);
setColour(juce::TextEditor::outlineColourId, juce::Colours::white);
setColour(juce::CaretComponent::caretColourId, Dracula::foreground);
setColour(juce::TextEditor::highlightColourId, Colours::grey);
// list box
setColour(juce::ListBox::backgroundColourId, Colours::darker);
// scroll bar
setColour(juce::ScrollBar::thumbColourId, juce::Colours::white);
setColour(juce::ScrollBar::trackColourId, Colours::veryDark);
setColour(juce::ScrollBar::backgroundColourId, Colours::veryDark);
// custom components
setColour(effectComponentBackgroundColourId, juce::Colours::transparentBlack);
setColour(effectComponentHandleColourId, Colours::veryDark);
// code editor
setColour(juce::CodeEditorComponent::backgroundColourId, Colours::darker);
setColour(juce::CodeEditorComponent::defaultTextColourId, Dracula::foreground);
setColour(juce::CodeEditorComponent::lineNumberBackgroundId, Colours::veryDark);
setColour(juce::CodeEditorComponent::lineNumberTextId, Dracula::foreground);
setColour(juce::CodeEditorComponent::highlightColourId, Colours::grey);
setColour(juce::CaretComponent::caretColourId, Dracula::foreground);
setColour(juce::TextEditor::highlightColourId, Colours::grey);
setColour(juce::TabbedButtonBar::tabOutlineColourId, Colours::veryDark);
setColour(juce::TabbedButtonBar::frontOutlineColourId, Colours::veryDark);
setColour(juce::TabbedButtonBar::tabTextColourId, juce::Colours::white);
setColour(juce::TabbedButtonBar::frontTextColourId, juce::Colours::white);
setColour(juce::TabbedComponent::outlineColourId, Colours::veryDark);
setColour(tabbedComponentBackgroundColourId, Colours::veryDark);
// envelope
setColour(EnvelopeComponent::Node, Colours::veryDark);
setColour(EnvelopeComponent::ReleaseNode, Colours::veryDark);
setColour(EnvelopeComponent::LoopNode, Colours::veryDark);
setColour(EnvelopeComponent::NodeOutline, juce::Colours::white);
setColour(EnvelopeComponent::Line, juce::Colours::white);
setColour(EnvelopeComponent::LoopLine, juce::Colours::white);
setColour(EnvelopeComponent::Background, Colours::veryDark);
setColour(EnvelopeComponent::GridLine, Colours::dark);
setColour(EnvelopeComponent::LegendText, juce::Colours::white);
setColour(EnvelopeComponent::LegendBackground, Colours::veryDark);
// midi keyboard
setColour(juce::MidiKeyboardComponent::blackNoteColourId, Colours::veryDark);
setColour(juce::MidiKeyboardComponent::whiteNoteColourId, juce::Colours::white);
setColour(juce::MidiKeyboardComponent::mouseOverKeyOverlayColourId, Colours::accentColor.withAlpha(0.3f));
setColour(juce::MidiKeyboardComponent::keyDownOverlayColourId, Colours::accentColor.withAlpha(0.7f));
setColour(juce::MidiKeyboardComponent::shadowColourId, juce::Colours::transparentBlack);
setColour(juce::MidiKeyboardComponent::upDownButtonBackgroundColourId, Colours::veryDark);
setColour(juce::MidiKeyboardComponent::upDownButtonArrowColourId, juce::Colours::white);
// UI colours
getCurrentColourScheme().setUIColour(ColourScheme::widgetBackground, Colours::veryDark);
getCurrentColourScheme().setUIColour(ColourScheme::UIColour::defaultFill, Colours::accentColor);
}
@ -175,6 +210,20 @@ void OscirenderLookAndFeel::drawMenuBarBackground(juce::Graphics& g, int width,
g.fillRect(r);
}
void OscirenderLookAndFeel::drawTooltip(juce::Graphics& g, const juce::String& text, int width, int height) {
juce::Rectangle<int> bounds (width, height);
auto cornerSize = 5.0f;
g.setColour(findColour(juce::TooltipWindow::backgroundColourId));
g.fillRect(bounds.toFloat());
g.setColour(findColour(juce::TooltipWindow::outlineColourId));
g.drawRect(bounds.toFloat().reduced(0.5f, 0.5f), 1.0f);
LookAndFeelHelpers::layoutTooltipText (text, findColour (juce::TooltipWindow::textColourId))
.draw (g, { static_cast<float> (width), static_cast<float> (height) });
}
juce::CodeEditorComponent::ColourScheme OscirenderLookAndFeel::getDefaultColourScheme() {
juce::CodeEditorComponent::ColourScheme cs;

Wyświetl plik

@ -1,6 +1,7 @@
#pragma once
#include <JuceHeader.h>
#include "UGen/ugen_JuceEnvelopeComponent.h"
enum ColourIds {
groupComponentBackgroundColourId,
@ -8,11 +9,10 @@ enum ColourIds {
effectComponentBackgroundColourId,
effectComponentHandleColourId,
sliderThumbOutlineColourId,
tabbedComponentBackgroundColourId,
};
namespace Colours {
const juce::Colour dark{0xff424242};
const juce::Colour dark{0xff353535};
const juce::Colour darker{0xff212121};
const juce::Colour veryDark{0xff111111};
const juce::Colour grey{0xff555555};
@ -34,6 +34,37 @@ namespace Dracula {
const juce::Colour yellow{0xfff1fa8c};
}
namespace LookAndFeelHelpers
{
static juce::Colour createBaseColour (juce::Colour buttonColour,
bool hasKeyboardFocus,
bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) noexcept
{
const float sat = hasKeyboardFocus ? 1.3f : 0.9f;
const juce::Colour baseColour (buttonColour.withMultipliedSaturation (sat));
if (shouldDrawButtonAsDown) return baseColour.contrasting (0.2f);
if (shouldDrawButtonAsHighlighted) return baseColour.contrasting (0.1f);
return baseColour;
}
static juce::TextLayout layoutTooltipText (const juce::String& text, juce::Colour colour) noexcept
{
const float tooltipFontSize = 13.0f;
const int maxToolTipWidth = 400;
juce::AttributedString s;
s.setJustification (juce::Justification::centred);
s.append (text, juce::Font (tooltipFontSize, juce::Font::bold), colour);
juce::TextLayout tl;
tl.createLayoutWithBalancedLineLengths (s, (float) maxToolTipWidth);
return tl;
}
}
class OscirenderLookAndFeel : public juce::LookAndFeel_V4 {
public:
OscirenderLookAndFeel();
@ -58,6 +89,6 @@ public:
bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override;
void drawMenuBarBackground(juce::Graphics& g, int width, int height, bool, juce::MenuBarComponent& menuBar) override;
juce::CodeEditorComponent::ColourScheme getDefaultColourScheme();
void drawTooltip(juce::Graphics& g, const juce::String& text, int width, int height) override;
};

Wyświetl plik

@ -83,6 +83,9 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
pluginEditor.fileUpdated(fileName);
};
fileName.setFont(juce::Font(16.0f, juce::Font::plain));
fileName.setText("filename");
fileName.onReturnKey = [this] {
createFile.triggerClick();
};

Wyświetl plik

@ -2,6 +2,8 @@
#include "PluginEditor.h"
MidiComponent::MidiComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), pluginEditor(editor) {
setText("MIDI Settings");
addAndMakeVisible(midiToggle);
addAndMakeVisible(keyboard);
@ -15,6 +17,7 @@ MidiComponent::MidiComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
envelope.setAdsrMode(true);
envelope.setEnv(audioProcessor.adsrEnv);
envelope.addListener(&audioProcessor);
envelope.setGrid(EnvelopeComponent::GridBoth, EnvelopeComponent::GridNone, 0.1, 0.25);
audioProcessor.attackTime->addListener(this);
audioProcessor.attackLevel->addListener(this);
@ -45,7 +48,6 @@ void MidiComponent::parameterValueChanged(int parameterIndex, float newValue) {
void MidiComponent::parameterGestureChanged(int parameterIndex, bool gestureIsStarting) {}
void MidiComponent::handleAsyncUpdate() {
DBG("MidiComponent::handleAsyncUpdate");
Env newEnv = Env(
{
0.0,
@ -71,14 +73,13 @@ void MidiComponent::handleAsyncUpdate() {
}
void MidiComponent::resized() {
auto area = getLocalBounds().reduced(5);
midiToggle.setBounds(area.removeFromTop(50));
envelope.setBounds(area.removeFromTop(200));
keyboard.setBounds(area.removeFromBottom(100));
auto area = getLocalBounds().withTrimmedTop(20).reduced(20);
midiToggle.setBounds(area.removeFromTop(30));
area.removeFromTop(5);
keyboard.setBounds(area.removeFromBottom(50));
envelope.setBounds(area);
}
void MidiComponent::paint(juce::Graphics& g) {
auto rect = getLocalBounds().reduced(5);
g.setColour(getLookAndFeel().findColour(groupComponentBackgroundColourId));
g.fillRect(rect);
juce::GroupComponent::paint(g);
}

Wyświetl plik

@ -4,7 +4,7 @@
#include "PluginProcessor.h"
class OscirenderAudioProcessorEditor;
class MidiComponent : public juce::Component, public juce::AudioProcessorParameter::Listener, public juce::AsyncUpdater {
class MidiComponent : public juce::GroupComponent, public juce::AudioProcessorParameter::Listener, public juce::AsyncUpdater {
public:
MidiComponent(OscirenderAudioProcessor&, OscirenderAudioProcessorEditor&);
~MidiComponent() override;
@ -20,8 +20,7 @@ private:
OscirenderAudioProcessorEditor& pluginEditor;
juce::ToggleButton midiToggle{"Enable MIDI"};
juce::MidiKeyboardState keyboardState;
juce::MidiKeyboardComponent keyboard{keyboardState, juce::MidiKeyboardComponent::horizontalKeyboard};
juce::MidiKeyboardComponent keyboard{audioProcessor.keyboardState, juce::MidiKeyboardComponent::horizontalKeyboard};
EnvelopeContainerComponent envelope;

Wyświetl plik

@ -73,6 +73,11 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
rotateX.setComponent(fixedRotateX);
rotateY.setComponent(fixedRotateY);
rotateZ.setComponent(fixedRotateZ);
juce::String tooltip = "Toggles whether the rotation around this axis is fixed, or changes according to the rotation speed.";
fixedRotateX->setTooltip(tooltip);
fixedRotateY->setTooltip(tooltip);
fixedRotateZ->setTooltip(tooltip);
}
ObjComponent::~ObjComponent() {

Wyświetl plik

@ -6,10 +6,6 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
{
juce::Desktop::getInstance().setDefaultLookAndFeel(&lookAndFeel);
setLookAndFeel(&lookAndFeel);
addAndMakeVisible(tabs);
tabs.addTab("Main", getLookAndFeel().findColour(tabbedComponentBackgroundColourId), &settings, false);
tabs.addTab("MIDI", getLookAndFeel().findColour(tabbedComponentBackgroundColourId), &midi, false);
addAndMakeVisible(volume);
menuBar.setModel(&menuBarModel);
@ -33,6 +29,7 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
juce::Path path;
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
collapseButton.setShape(path, false, true, true);
collapseButton.setMouseCursor(juce::MouseCursor::PointingHandCursor);
colourScheme = lookAndFeel.getDefaultColourScheme();
@ -62,6 +59,7 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
layout.setItemLayout(1, 7, 7, 7);
layout.setItemLayout(2, -0.1, -1.0, -0.3);
addAndMakeVisible(settings);
addAndMakeVisible(resizerBar);
}
@ -115,6 +113,8 @@ void OscirenderAudioProcessorEditor::resized() {
juce::Component* columns[] = { &dummy, &resizerBar, codeEditors[index].get() };
DBG("area: " << area.toString());
layout.layOutComponents(columns, 3, area.getX(), area.getY(), area.getWidth(), area.getHeight(), false, true);
auto dummyBounds = dummy.getBounds();
collapseButton.setBounds(dummyBounds.removeFromRight(20));
@ -123,6 +123,7 @@ void OscirenderAudioProcessorEditor::resized() {
} else {
codeEditors[index]->setBounds(0, 0, 0, 0);
resizerBar.setBounds(0, 0, 0, 0);
collapseButton.setBounds(area.removeFromRight(20));
}
} else {
@ -139,9 +140,8 @@ void OscirenderAudioProcessorEditor::resized() {
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
collapseButton.setShape(path, false, true, true);
}
tabs.setBounds(area);
settings.setBounds(area);
repaint();
}

Wyświetl plik

@ -38,8 +38,6 @@ public:
private:
OscirenderAudioProcessor& audioProcessor;
juce::TabbedComponent tabs{juce::TabbedButtonBar::TabsAtTop};
MidiComponent midi{audioProcessor, *this};
SettingsComponent settings{audioProcessor, *this};
VolumeComponent volume{audioProcessor};
std::vector<std::shared_ptr<juce::CodeDocument>> codeDocuments;
@ -58,7 +56,7 @@ private:
juce::StretchableLayoutManager layout;
juce::StretchableLayoutResizerBar resizerBar{&layout, 1, true};
juce::TooltipWindow tooltipWindow{this};
juce::TooltipWindow tooltipWindow{this, 0};
std::atomic<bool> updatingDocumentsWithParserLock = false;

Wyświetl plik

@ -36,68 +36,63 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<BitCrushEffect>(),
new EffectParameter("Bit Crush", "bitCrush", VERSION_HINT, 0.0, 0.0, 1.0),
"bitCrush"
new EffectParameter("Bit Crush", "Limits the resolution of points drawn to the screen, making the image look pixelated, and making the audio sound more 'digital' and distorted.", "bitCrush", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<BulgeEffect>(),
new EffectParameter("Bulge", "bulge", VERSION_HINT, 0.0, 0.0, 1.0),
"bulge"
new EffectParameter("Bulge", "Applies a bulge that makes the centre of the image larger, and squishes the edges of the image. This applies a distortion to the audio.", "bulge", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<RotateEffect>(),
new EffectParameter("2D Rotate", "2DRotateSpeed", VERSION_HINT, 0.0, 0.0, 1.0),
"2DRotate"
new EffectParameter("2D Rotate", "Rotates the image, and pans the audio.", "2DRotateSpeed", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<VectorCancellingEffect>(),
new EffectParameter("Vector Cancelling", "vectorCancelling", VERSION_HINT, 0.0, 0.0, 1.0),
"vectorCancelling"
new EffectParameter("Vector Cancelling", "Inverts the audio and image every few samples to 'cancel out' the audio, making the audio quiet, and distorting the image.", "vectorCancelling", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<DistortEffect>(false),
new EffectParameter("Distort X", "distortX", VERSION_HINT, 0.0, 0.0, 1.0),
"distortX"
new EffectParameter("Distort X", "Distorts the image in the horizontal direction by jittering the audio sample being drawn.", "distortX", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<DistortEffect>(true),
new EffectParameter("Distort Y", "distortY", VERSION_HINT, 0.0, 0.0, 1.0),
"distortY"
new EffectParameter("Distort Y", "Distorts the image in the vertical direction by jittering the audio sample being drawn.", "distortY", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
input.x += values[0];
input.y += values[1];
return input;
}, std::vector<EffectParameter*>{new EffectParameter("Translate X", "translateX", VERSION_HINT, 0.0, -1.0, 1.0), new EffectParameter("Translate Y", "translateY", VERSION_HINT, 0.0, -1.0, 1.0)},
"translate"
}, std::vector<EffectParameter*>{
new EffectParameter("Translate X", "Moves the image horizontally.", "translateX", VERSION_HINT, 0.0, -1.0, 1.0),
new EffectParameter("Translate Y", "Moves the image vertically.", "translateY", VERSION_HINT, 0.0, -1.0, 1.0)
}
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<SmoothEffect>(),
new EffectParameter("Smoothing", "smoothing", VERSION_HINT, 0.0, 0.0, 1.0),
"smoothing"
new EffectParameter("Smoothing", "This works as a low-pass frequency filter that removes high frequencies, making the image look smoother, and audio sound less harsh.", "smoothing", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
wobbleEffect,
new EffectParameter("Wobble", "wobble", VERSION_HINT, 0.0, 0.0, 1.0),
"wobble"
new EffectParameter("Wobble", "Adds a sine wave of the prominent frequency in the audio currently playing. The sine wave's frequency is slightly offset to create a subtle 'wobble' in the image. Increasing the slider increases the strength of the wobble.", "wobble", VERSION_HINT, 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
delayEffect,
std::vector<EffectParameter*>{new EffectParameter("Delay Decay", "delayDecay", VERSION_HINT, 0.0, 0.0, 1.0), new EffectParameter("Delay Length", "delayLength", VERSION_HINT, 0.5, 0.0, 1.0)},
"delay"
std::vector<EffectParameter*>{
new EffectParameter("Delay Decay", "Adds repetitions, delays, or echos to the audio. This slider controls the volume of the echo.", "delayDecay", VERSION_HINT, 0.0, 0.0, 1.0),
new EffectParameter("Delay Length", "Controls the time in seconds between echos.", "delayLength", VERSION_HINT, 0.5, 0.0, 1.0)
}
));
toggleableEffects.push_back(std::make_shared<Effect>(
perspectiveEffect,
std::vector<EffectParameter*>{
new EffectParameter("3D Perspective", "perspectiveStrength", VERSION_HINT, 0.0, 0.0, 1.0),
new EffectParameter("Depth (z)", "perspectiveZPos", VERSION_HINT, 0.1, 0.0, 1.0),
new EffectParameter("Rotate Speed", "perspectiveRotateSpeed", VERSION_HINT, 0.0, -1.0, 1.0),
new EffectParameter("Rotate X", "perspectiveRotateX", VERSION_HINT, 1.0, -1.0, 1.0),
new EffectParameter("Rotate Y", "perspectiveRotateY", VERSION_HINT, 1.0, -1.0, 1.0),
new EffectParameter("Rotate Z", "perspectiveRotateZ", VERSION_HINT, 0.0, -1.0, 1.0),
},
"perspective"
new EffectParameter("3D Perspective", "Controls the strength of the 3D perspective effect which treats the image as a 3D object that can be rotated.", "perspectiveStrength", VERSION_HINT, 0.0, 0.0, 1.0),
new EffectParameter("Depth (z)", "Controls how far away the 3D object is drawn away from the camera (the Z position).", "perspectiveZPos", VERSION_HINT, 0.1, 0.0, 1.0),
new EffectParameter("Rotate Speed", "Controls how fast the 3D object rotates in the direction determined by the rotation sliders below.", "perspectiveRotateSpeed", VERSION_HINT, 0.0, -1.0, 1.0),
new EffectParameter("Rotate X", "Controls the rotation of the object in the X axis.", "perspectiveRotateX", VERSION_HINT, 1.0, -1.0, 1.0),
new EffectParameter("Rotate Y", "Controls the rotation of the object in the Y axis.", "perspectiveRotateY", VERSION_HINT, 1.0, -1.0, 1.0),
new EffectParameter("Rotate Z", "Controls the rotation of the object in the Z axis.", "perspectiveRotateZ", VERSION_HINT, 0.0, -1.0, 1.0),
}
));
toggleableEffects.push_back(traceMax);
toggleableEffects.push_back(traceMin);
@ -275,8 +270,12 @@ void OscirenderAudioProcessor::addLuaSlider() {
luaEffects.push_back(std::make_shared<Effect>(
std::make_shared<LuaEffect>(sliderName, *this),
new EffectParameter("Lua " + sliderName, "lua" + sliderName, VERSION_HINT, 0.0, 0.0, 1.0, 0.001, false),
"lua" + sliderName
new EffectParameter(
"Lua Slider " + sliderName,
"Controls the value of the Lua variable called slider_" + sliderName + ".",
"lua" + sliderName,
VERSION_HINT, 0.0, 0.0, 1.0, 0.001, false
)
));
auto& effect = luaEffects.back();
@ -480,6 +479,9 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
buffer.clear(i, 0, buffer.getNumSamples());
}
// merge keyboard state and midi messages
keyboardState.processNextMidiBuffer(midiMessages, 0, buffer.getNumSamples(), true);
bool usingInput = inputEnabled->getBoolValue();
bool usingMidi = midiEnabled->getBoolValue();

Wyświetl plik

@ -81,24 +81,36 @@ public:
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
frequency = values[0];
return input;
}, new EffectParameter("Frequency", "frequency", VERSION_HINT, 440.0, 0.0, 12000.0, 0.1),
"Controls how many times per second the image is drawn, thereby controlling the pitch of the sound. Lower frequencies result in more-accurately drawn images, but more flickering, and vice versa."
}, new EffectParameter(
"Frequency",
"Controls how many times per second the image is drawn, thereby controlling the pitch of the sound. Lower frequencies result in more-accurately drawn images, but more flickering, and vice versa.",
"frequency",
VERSION_HINT, 440.0, 0.0, 12000.0, 0.1
)
);
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
volume = values[0];
return input;
}, new EffectParameter("Volume", "volume", VERSION_HINT, 1.0, 0.0, 3.0),
"Controls the volume of the sound. Works by scaling the image and sound by a factor."
}, new EffectParameter(
"Volume",
"Controls the volume of the sound. Works by scaling the image and sound by a factor.",
"volume",
VERSION_HINT, 1.0, 0.0, 3.0
)
);
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
threshold = values[0];
return input;
}, new EffectParameter("Threshold", "threshold", VERSION_HINT, 1.0, 0.0, 1.0),
"Clips the sound and image to a maximum value. Applying a harsher threshold results in a more distorted sound."
}, new EffectParameter(
"Threshold",
"Clips the sound and image to a maximum value. Applying a harsher threshold results in a more distorted sound.",
"threshold",
VERSION_HINT, 1.0, 0.0, 1.0
)
);
std::shared_ptr<Effect> focalLength = std::make_shared<Effect>(
@ -109,8 +121,12 @@ public:
camera->setFocalLength(values[0]);
}
return input;
}, new EffectParameter("Focal length", "objFocalLength", VERSION_HINT, 1.0, 0.0, 2.0),
"Controls the focal length of the camera being used to render the 3D object. A lower focal length results in a wider field of view, distorting the image, and making the image smaller."
}, new EffectParameter(
"Focal length",
"Controls the focal length of the camera being used to render the 3D object. A lower focal length results in a wider field of view, distorting the image, and making the image smaller.",
"objFocalLength",
VERSION_HINT, 1.0, 0.0, 2.0
)
);
BooleanParameter* fixedRotateX = new BooleanParameter("Object Fixed Rotate X", "objFixedRotateX", VERSION_HINT, false);
@ -129,8 +145,12 @@ public:
}
}
return input;
}, new EffectParameter("Object Rotate X", "objRotateX", VERSION_HINT, 1.0, -1.0, 1.0),
"Controls the rotation of the 3D object around the X axis. When Object Fixed Rotate X is enabled, the object is unaffected by the rotation speed, and remains in a fixed position."
}, new EffectParameter(
"Object Rotate X",
"Controls the rotation of the 3D object around the X axis. When Object Fixed Rotate X is enabled, the object is unaffected by the rotation speed, and remains in a fixed position.",
"objRotateX",
VERSION_HINT, 1.0, -1.0, 1.0
)
);
std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
@ -145,8 +165,12 @@ public:
}
}
return input;
}, new EffectParameter("Object Rotate Y", "objRotateY", VERSION_HINT, 1.0, -1.0, 1.0),
"Controls the rotation of the 3D object around the Y axis. When Object Fixed Rotate Y is enabled, the object is unaffected by the rotation speed, and remains in a fixed position."
}, new EffectParameter(
"Object Rotate Y",
"Controls the rotation of the 3D object around the Y axis. When Object Fixed Rotate Y is enabled, the object is unaffected by the rotation speed, and remains in a fixed position.",
"objRotateY",
VERSION_HINT, 1.0, -1.0, 1.0
)
);
std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
@ -161,8 +185,12 @@ public:
}
}
return input;
}, new EffectParameter("Object Rotate Z", "objRotateZ", VERSION_HINT, 0.0, -1.0, 1.0),
"Controls the rotation of the 3D object around the Z axis. When Object Fixed Rotate Z is enabled, the object is unaffected by the rotation speed, and remains in a fixed position."
}, new EffectParameter(
"Object Rotate Z",
"Controls the rotation of the 3D object around the Z axis. When Object Fixed Rotate Z is enabled, the object is unaffected by the rotation speed, and remains in a fixed position.",
"objRotateZ",
VERSION_HINT, 0.0, -1.0, 1.0
)
);
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
@ -172,27 +200,39 @@ public:
obj->setRotationSpeed(values[0]);
}
return input;
}, new EffectParameter("Rotate Speed", "objRotateSpeed", VERSION_HINT, 0.0, -1.0, 1.0),
"Controls the speed at which the 3D object rotates. A negative value results in the object rotating in the opposite direction. The rotate speed is scaled by the different Object Rotate Axis values to rotate the object."
}, new EffectParameter(
"Rotate Speed",
"Controls the speed at which the 3D object rotates. A negative value results in the object rotating in the opposite direction. The rotate speed is scaled by the different Object Rotate Axis values to rotate the object.",
"objRotateSpeed",
VERSION_HINT, 0.0, -1.0, 1.0
)
);
std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
return input;
}, new EffectParameter("Trace max", "traceMax", VERSION_HINT, 1.0, 0.0, 1.0),
"Defines the maximum proportion of the image that is drawn before skipping to the next frame. This has the effect of 'tracing' out the image from a single dot when animated. By default, we draw until the end of the frame, so this value is 1.0."
}, new EffectParameter(
"Trace max",
"Defines the maximum proportion of the image that is drawn before skipping to the next frame. This has the effect of 'tracing' out the image from a single dot when animated. By default, we draw until the end of the frame, so this value is 1.0.",
"traceMax",
VERSION_HINT, 1.0, 0.0, 1.0
)
);
std::shared_ptr<Effect> traceMin = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
return input;
}, new EffectParameter("Trace min", "traceMin", VERSION_HINT, 0.0, 0.0, 1.0),
"Defines the proportion of the image that drawing starts from. This has the effect of 'tracing' out the image from a single dot when animated. By default, we start drawing from the beginning of the frame, so this value is 0.0."
}, new EffectParameter(
"Trace min",
"Defines the proportion of the image that drawing starts from. This has the effect of 'tracing' out the image from a single dot when animated. By default, we start drawing from the beginning of the frame, so this value is 0.0.",
"traceMin",
VERSION_HINT, 0.0, 0.0, 1.0
)
);
std::shared_ptr<DelayEffect> delayEffect = std::make_shared<DelayEffect>();
std::shared_ptr<PerspectiveEffect> perspectiveEffect = std::make_shared<PerspectiveEffect>(VERSION_HINT);
BooleanParameter* midiEnabled = new BooleanParameter("MIDI Enabled", "midiEnabled", VERSION_HINT, !juce::JUCEApplicationBase::isStandaloneApp());
BooleanParameter* midiEnabled = new BooleanParameter("MIDI Enabled", "midiEnabled", VERSION_HINT, false);
BooleanParameter* inputEnabled = new BooleanParameter("Audio Input Enabled", "inputEnabled", VERSION_HINT, false);
std::atomic<float> frequency = 440.0f;
@ -207,14 +247,14 @@ public:
std::atomic<bool> objectServerRendering = false;
juce::ChangeBroadcaster fileChangeBroadcaster;
FloatParameter* attackTime = new FloatParameter("Attack Time", "attackTime", VERSION_HINT, 0.05, 0.0, 1.0);
FloatParameter* attackTime = new FloatParameter("Attack Time", "attackTime", VERSION_HINT, 0.005, 0.0, 1.0);
FloatParameter* attackLevel = new FloatParameter("Attack Level", "attackLevel", VERSION_HINT, 1.0, 0.0, 1.0);
FloatParameter* decayTime = new FloatParameter("Decay Time", "decayTime", VERSION_HINT, 0.05, 0.0, 1.0);
FloatParameter* sustainLevel = new FloatParameter("Sustain Level", "sustainLevel", VERSION_HINT, 0.8, 0.0, 1.0);
FloatParameter* releaseTime = new FloatParameter("Release Time", "releaseTime", VERSION_HINT, 0.2, 0.0, 1.0);
FloatParameter* decayTime = new FloatParameter("Decay Time", "decayTime", VERSION_HINT, 0.095, 0.0, 1.0);
FloatParameter* sustainLevel = new FloatParameter("Sustain Level", "sustainLevel", VERSION_HINT, 0.6, 0.0, 1.0);
FloatParameter* releaseTime = new FloatParameter("Release Time", "releaseTime", VERSION_HINT, 0.4, 0.0, 1.0);
FloatParameter* attackShape = new FloatParameter("Attack Shape", "attackShape", VERSION_HINT, 5, -50, 50);
FloatParameter* decayShape = new FloatParameter("Decay Shape", "decayShape", VERSION_HINT, -20, -50, 50);
FloatParameter* releaseShape = new FloatParameter("Release Shape", "releaseShape", VERSION_HINT, 5,-50, 50);
FloatParameter* releaseShape = new FloatParameter("Release Shape", "releaseShape", VERSION_HINT, -5,-50, 50);
Env adsrEnv = Env::adsr(
attackTime->getValueUnnormalised(),
@ -225,6 +265,8 @@ public:
std::vector<EnvCurve>{ attackShape->getValueUnnormalised(), decayShape->getValueUnnormalised(), releaseShape->getValueUnnormalised() }
);
juce::MidiKeyboardState keyboardState;
private:
juce::SpinLock consumerLock;
std::vector<std::shared_ptr<BufferConsumer>> consumers;

Wyświetl plik

@ -4,19 +4,25 @@
SettingsComponent::SettingsComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), pluginEditor(editor) {
addAndMakeVisible(effects);
addAndMakeVisible(main);
addAndMakeVisible(columnResizerBar);
addAndMakeVisible(rowResizerBar);
addAndMakeVisible(midiResizerBar);
addAndMakeVisible(mainResizerBar);
addAndMakeVisible(effectResizerBar);
addAndMakeVisible(midi);
addChildComponent(lua);
addChildComponent(obj);
addChildComponent(txt);
columnLayout.setItemLayout(0, -0.1, -0.9, -0.4);
columnLayout.setItemLayout(1, 7, 7, 7);
columnLayout.setItemLayout(2, -0.1, -0.9, -0.6);
midiLayout.setItemLayout(0, -0.1, -1.0, -1.0);
midiLayout.setItemLayout(1, 7, 7, 7);
midiLayout.setItemLayout(2, CLOSED_PREF_SIZE, -0.9, CLOSED_PREF_SIZE);
rowLayout.setItemLayout(0, -0.1, -1.0, -0.63);
rowLayout.setItemLayout(1, 7, 7, 7);
rowLayout.setItemLayout(2, -0.1, -0.9, -0.37);
mainLayout.setItemLayout(0, -0.1, -0.9, -0.4);
mainLayout.setItemLayout(1, 7, 7, 7);
mainLayout.setItemLayout(2, -0.1, -0.9, -0.6);
effectLayout.setItemLayout(0, -0.1, -1.0, -0.63);
effectLayout.setItemLayout(1, 7, 7, 7);
effectLayout.setItemLayout(2, -0.1, -0.9, -0.37);
}
@ -29,8 +35,11 @@ void SettingsComponent::resized() {
juce::Component dummy;
juce::Component* columns[] = { &main, &columnResizerBar, &dummy };
columnLayout.layOutComponents(columns, 3, area.getX(), area.getY(), area.getWidth(), area.getHeight(), false, true);
juce::Component* midiComponents[] = { &dummy, &midiResizerBar, &midi };
midiLayout.layOutComponents(midiComponents, 3, area.getX(), area.getY(), area.getWidth(), area.getHeight(), true, true);
juce::Component* columns[] = { &main, &mainResizerBar, &dummy };
mainLayout.layOutComponents(columns, 3, dummy.getX(), dummy.getY(), dummy.getWidth(), dummy.getHeight(), false, true);
juce::Component* effectSettings = nullptr;
@ -42,14 +51,16 @@ void SettingsComponent::resized() {
effectSettings = &txt;
}
juce::Component* rows[] = { &effects, &rowResizerBar, effectSettings };
juce::Component* rows[] = { &effects, &effectResizerBar, effectSettings };
// use the dummy component to work out the bounds of the rows
if (effectSettings != nullptr) {
rowLayout.layOutComponents(rows, 3, dummy.getX(), dummy.getY(), dummy.getWidth(), dummy.getHeight(), true, true);
effectLayout.layOutComponents(rows, 3, dummy.getX(), dummy.getY(), dummy.getWidth(), dummy.getHeight(), true, true);
} else {
effects.setBounds(dummy.getBounds());
}
repaint();
}
void SettingsComponent::fileUpdated(juce::String fileName) {
@ -77,3 +88,49 @@ void SettingsComponent::update() {
void SettingsComponent::disableMouseRotation() {
obj.disableMouseRotation();
}
void SettingsComponent::toggleMidiComponent() {
double minSize, maxSize, preferredSize;
midiLayout.getItemLayout(2, minSize, maxSize, preferredSize);
if (preferredSize == CLOSED_PREF_SIZE) {
midiLayout.setItemLayout(0, -0.1, -1.0, -0.7);
midiLayout.setItemLayout(2, CLOSED_PREF_SIZE, -0.9, -0.3);
} else {
midiLayout.setItemLayout(0, -0.1, -1.0, -1.0);
midiLayout.setItemLayout(2, CLOSED_PREF_SIZE, -0.9, CLOSED_PREF_SIZE);
}
resized();
}
void SettingsComponent::mouseMove(const juce::MouseEvent& event) {
// if mouse over midi component, change cursor to link cursor
if (midi.getBounds().removeFromTop(CLOSED_PREF_SIZE).contains(event.getPosition())) {
setMouseCursor(juce::MouseCursor::PointingHandCursor);
} else {
setMouseCursor(juce::MouseCursor::NormalCursor);
}
}
void SettingsComponent::mouseDown(const juce::MouseEvent& event) {
// if mouse over midi component, toggle midi component
if (midi.getBounds().removeFromTop(CLOSED_PREF_SIZE).contains(event.getPosition())) {
toggleMidiComponent();
}
}
void SettingsComponent::paint(juce::Graphics& g) {
// add drop shadow to each component
auto dc = juce::DropShadow(juce::Colours::black, 5, juce::Point<int>(0, 0));
dc.drawForRectangle(g, main.getBounds());
dc.drawForRectangle(g, effects.getBounds());
dc.drawForRectangle(g, midi.getBounds());
if (lua.isVisible()) {
dc.drawForRectangle(g, lua.getBounds());
} else if (obj.isVisible()) {
dc.drawForRectangle(g, obj.getBounds());
} else if (txt.isVisible()) {
dc.drawForRectangle(g, txt.getBounds());
}
}

Wyświetl plik

@ -7,6 +7,7 @@
#include "ObjComponent.h"
#include "TxtComponent.h"
#include "EffectsComponent.h"
#include "MidiComponent.h"
class OscirenderAudioProcessorEditor;
class SettingsComponent : public juce::Component {
@ -17,6 +18,10 @@ public:
void fileUpdated(juce::String fileName);
void update();
void disableMouseRotation();
void toggleMidiComponent();
void mouseMove(const juce::MouseEvent& event) override;
void mouseDown(const juce::MouseEvent& event) override;
void paint(juce::Graphics& g) override;
private:
OscirenderAudioProcessor& audioProcessor;
@ -27,11 +32,16 @@ private:
ObjComponent obj{audioProcessor, pluginEditor};
TxtComponent txt{audioProcessor, pluginEditor};
EffectsComponent effects{audioProcessor, pluginEditor};
MidiComponent midi{audioProcessor, pluginEditor};
juce::StretchableLayoutManager columnLayout;
juce::StretchableLayoutResizerBar columnResizerBar{&columnLayout, 1, true};
juce::StretchableLayoutManager rowLayout;
juce::StretchableLayoutResizerBar rowResizerBar{&rowLayout, 1, false};
const double CLOSED_PREF_SIZE = 30.0;
juce::StretchableLayoutManager midiLayout;
juce::StretchableLayoutResizerBar midiResizerBar{&midiLayout, 1, false};
juce::StretchableLayoutManager mainLayout;
juce::StretchableLayoutResizerBar mainResizerBar{&mainLayout, 1, true};
juce::StretchableLayoutManager effectLayout;
juce::StretchableLayoutResizerBar effectResizerBar{&effectLayout, 1, false};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SettingsComponent)
};

Wyświetl plik

@ -13,6 +13,7 @@
UGEN++ can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
either version 2 of the License, or (at your option) any later version.
UGEN++ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -88,15 +89,19 @@ void EnvelopeHandleComponentConstrainer::setAdjacentHandleLimits(int setLeftLimi
}
EnvelopeHandleComponent::EnvelopeHandleComponent()
: dontUpdateTimeAndValue(false),
lastX(-1),
lastY(-1),
resizeLimits(this),
shouldLockTime(false),
shouldLockValue(false),
ignoreDrag(false)
: dontUpdateTimeAndValue(false),
lastX(-1),
lastY(-1),
resizeLimits(this),
shouldLockTime(false),
shouldLockValue(false),
shouldDraw(!shouldLockTime || !shouldLockValue),
ignoreDrag(false)
{
setMouseCursor(juce::MouseCursor::CrosshairCursor);
if (shouldDraw) {
setMouseCursor(juce::MouseCursor::DraggingHandCursor);
}
resetOffsets();
}
@ -149,70 +154,88 @@ void EnvelopeHandleComponent::updateLegend()
int width = getParentWidth();
int places;
if(width >= 165) {
if(env && env->isLoopNode(this))
text << "(Loop) ";
else if(env && env->isReleaseNode(this))
text << "(Release) ";
else
text << "Point ";
if (width >= 115) {
places = 3;
} else if (width >= 100) {
places = 2;
} else {
places = 1;
}
else if(width >= 140) {
text << "Point ";
places = 3;
} else if(width >= 115) {
text << "Pt ";
places = 3;
} else if(width >= 100) {
text << "Pt ";
places = 2;
} else if(width >= 85) {
text << "Pt ";
places = 1;
} else if(width >= 65) {
text << "P ";
places = 1;
if (env->getAdsrMode()) {
int index = env->getHandleIndex(this);
Env envelope = env->getEnv();
double envTime = envelope.getTimes()[index - 1];
if (index == 1) {
text = "Attack time (s): " + juce::String(legend->mapTime(envTime), places);
text << ", Attack level: " << juce::String(legend->mapValue(value), places);
} else if (index == 2) {
text = "Decay time (s): " + juce::String(legend->mapTime(envTime), places);
text << ", Sustain level: " << juce::String(legend->mapValue(value), places);
} else {
text = "Release time (s): " + juce::String(legend->mapTime(envTime), places);
}
} else {
places = 1;
if (width >= 165) {
if (env && env->isLoopNode(this))
text << "(Loop) ";
else if (env && env->isReleaseNode(this))
text << "(Release) ";
else
text << "Point ";
} else if (width >= 140) {
text << "Point ";
} else if (width >= 115) {
text << "Pt ";
} else if (width >= 100) {
text << "Pt ";
} else if (width >= 85) {
text << "Pt ";
} else if (width >= 65) {
text << "P ";
}
text << (getHandleIndex())
<< ": "
<< juce::String(legend->mapTime(time), places) << legend->getTimeUnits()
<< ", "
<< juce::String(legend->mapValue(value), places) << legend->getValueUnits();
}
text << (getHandleIndex())
<< ": "
<< juce::String(legend->mapTime(time), places) << legend->getTimeUnits()
<< ", "
<< juce::String(legend->mapValue(value), places) << legend->getValueUnits();
getParentComponent()->setLegendText(text);
}
void EnvelopeHandleComponent::paint(juce::Graphics& g)
{
EnvelopeComponent *env = getParentComponent();
juce::Colour handleColour;
if(env == 0)
{
handleColour = juce::Colour(0xFF69B4FF);
if (shouldDraw) {
EnvelopeComponent *env = getParentComponent();
juce::Colour handleColour;
if(env == 0)
{
handleColour = juce::Colour(0xFF69B4FF);
}
else if(env->isReleaseNode(this))
{
handleColour = findColour(EnvelopeComponent::ReleaseNode);
}
else if(env->isLoopNode(this))
{
handleColour = findColour(EnvelopeComponent::LoopNode);
}
else
{
handleColour = findColour(EnvelopeComponent::Node);
}
g.setColour(handleColour);
g.fillEllipse(1, 1, getWidth() - 2, getHeight() - 2);
g.setColour(findColour(EnvelopeComponent::NodeOutline));
g.drawEllipse(1, 1, getWidth() - 2, getHeight() - 2, 1.0f);
}
else if(env->isReleaseNode(this))
{
handleColour = env->getEnvColour(EnvelopeComponent::ReleaseNode);
}
else if(env->isLoopNode(this))
{
handleColour = env->getEnvColour(EnvelopeComponent::LoopNode);
}
else
{
handleColour = env->getEnvColour(EnvelopeComponent::Node);
}
g.setColour(handleColour);
g.fillRect(1, 1, getWidth()-2, getHeight()-2);
}
void EnvelopeHandleComponent::moved()
@ -236,8 +259,12 @@ void EnvelopeHandleComponent::mouseEnter(const juce::MouseEvent& e)
printf("MyEnvelopeHandleComponent::mouseEnter\n");
#endif
setMouseCursor(juce::MouseCursor::CrosshairCursor);
updateLegend();
if (shouldDraw) {
setMouseCursor(juce::MouseCursor::DraggingHandCursor);
updateLegend();
} else {
setMouseCursor(juce::MouseCursor::NormalCursor);
}
}
void EnvelopeHandleComponent::mouseExit(const juce::MouseEvent& e)
@ -256,60 +283,62 @@ void EnvelopeHandleComponent::mouseDown(const juce::MouseEvent& e)
printf("MyEnvelopeHandleComponent::mouseDown (%d, %d)\n", e.x, e.y);
#endif
setMouseCursor(juce::MouseCursor::NoCursor);
if(e.mods.isShiftDown()) {
if(!shouldLockTime && !shouldLockValue)
{
getParentComponent()->setLegendTextToDefault();
removeThisHandle();
if (shouldDraw) {
setMouseCursor(juce::MouseCursor::NoCursor);
if(e.mods.isShiftDown()) {
if(!shouldLockTime && !shouldLockValue)
{
getParentComponent()->setLegendTextToDefault();
removeThisHandle();
}
return; // dont send drag msg
}
//else if(e.mods.isCtrlDown())
//{
// if(getParentComponent()->getAllowNodeEditing())
// {
// ignoreDrag = true;
//
// if(PopupComponent::getActivePopups() < 1)
// {
// EnvelopeNodePopup::create(this, getScreenX()+e.x, getScreenY()+e.y);
// }
// }
//}
else
{
offsetX = e.x;
offsetY = e.y;
resizeLimits.setMinimumOnscreenAmounts(HANDLESIZE,HANDLESIZE,HANDLESIZE,HANDLESIZE);
EnvelopeHandleComponent* previousHandle = getPreviousHandle();
EnvelopeHandleComponent* nextHandle = getNextHandle();
int leftLimit = previousHandle == 0 ? 0 : previousHandle->getX()+2;
int rightLimit = nextHandle == 0 ? getParentWidth()-HANDLESIZE : nextHandle->getX()-2;
// int leftLimit = previousHandle == 0 ? 0 : previousHandle->getX();
// int rightLimit = nextHandle == 0 ? getParentWidth()-HANDLESIZE : nextHandle->getX();
resizeLimits.setAdjacentHandleLimits(leftLimit, rightLimit);
dragger.startDraggingComponent(this, e);//&resizeLimits);
}
return; // dont send drag msg
}
//else if(e.mods.isCtrlDown())
//{
// if(getParentComponent()->getAllowNodeEditing())
// {
// ignoreDrag = true;
//
// if(PopupComponent::getActivePopups() < 1)
// {
// EnvelopeNodePopup::create(this, getScreenX()+e.x, getScreenY()+e.y);
// }
// }
//}
else
{
offsetX = e.x;
offsetY = e.y;
resizeLimits.setMinimumOnscreenAmounts(HANDLESIZE,HANDLESIZE,HANDLESIZE,HANDLESIZE);
EnvelopeHandleComponent* previousHandle = getPreviousHandle();
EnvelopeHandleComponent* nextHandle = getNextHandle();
int leftLimit = previousHandle == 0 ? 0 : previousHandle->getX()+2;
int rightLimit = nextHandle == 0 ? getParentWidth()-HANDLESIZE : nextHandle->getX()-2;
// int leftLimit = previousHandle == 0 ? 0 : previousHandle->getX();
// int rightLimit = nextHandle == 0 ? getParentWidth()-HANDLESIZE : nextHandle->getX();
resizeLimits.setAdjacentHandleLimits(leftLimit, rightLimit);
dragger.startDraggingComponent(this, e);//&resizeLimits);
getParentComponent()->sendStartDrag();
}
getParentComponent()->sendStartDrag();
}
void EnvelopeHandleComponent::mouseDrag(const juce::MouseEvent& e)
{
if(ignoreDrag == true) return;
if(ignoreDrag || !shouldDraw) return;
dragger.dragComponent(this, e, &resizeLimits);
@ -350,7 +379,11 @@ void EnvelopeHandleComponent::mouseUp(const juce::MouseEvent& e)
printf("MyEnvelopeHandleComponent::mouseUp\n");
#endif
if(ignoreDrag == true)
if (!shouldDraw) {
goto exit;
}
if(ignoreDrag)
{
ignoreDrag = false;
goto exit;
@ -361,7 +394,7 @@ void EnvelopeHandleComponent::mouseUp(const juce::MouseEvent& e)
env->quantiseHandle(this);
// }
setMouseCursor(juce::MouseCursor::CrosshairCursor);
setMouseCursor(juce::MouseCursor::DraggingHandCursor);
setMousePositionToThisHandle();
offsetX = 0;
@ -504,22 +537,26 @@ void EnvelopeHandleComponent::lockTime(double timeToLock)
{
setTime(timeToLock);
shouldLockTime = true;
recalculateShouldDraw();
}
void EnvelopeHandleComponent::lockValue(double valueToLock)
{
setValue(valueToLock);
shouldLockValue = true;
recalculateShouldDraw();
}
void EnvelopeHandleComponent::unlockTime()
{
shouldLockTime = false;
recalculateShouldDraw();
}
void EnvelopeHandleComponent::unlockValue()
{
shouldLockValue = false;
recalculateShouldDraw();
}
void EnvelopeHandleComponent::recalculatePosition()
@ -532,6 +569,10 @@ void EnvelopeHandleComponent::recalculatePosition()
getParentComponent()->repaint();
}
void EnvelopeHandleComponent::recalculateShouldDraw() {
shouldDraw = !shouldLockTime || !shouldLockValue;
}
EnvelopeComponent::EnvelopeComponent()
: minNumHandles(0),
@ -554,16 +595,6 @@ EnvelopeComponent::EnvelopeComponent()
{
setMouseCursor(juce::MouseCursor::NormalCursor);
setBounds(0, 0, 200, 200); // non-zero size to start with
colours[Node] = juce::Colour(0xFF69B4FF);
colours[ReleaseNode] = juce::Colour(0xFFB469FF);
colours[LoopNode] = juce::Colour(0xFF69FFB4);
colours[Line] = juce::Colour(0xFFFFFFFF);
colours[LoopLine] = juce::Colour(0xFFB469FF);
colours[Background] = juce::Colour(0xFF555555);
colours[GridLine] = juce::Colour(0xFF888888);
colours[LegendText] = juce::Colour(0xFF000000);
colours[LegendBackground] = juce::Colour(0xFF696969);
}
EnvelopeComponent::~EnvelopeComponent()
@ -719,8 +750,8 @@ void EnvelopeComponent::paint(juce::Graphics& g)
time = nextTime;
}
g.setColour(colours[Line]);
g.strokePath (path, juce::PathStrokeType(1.0f));
g.setColour(findColour(Line));
g.strokePath (path, juce::PathStrokeType(2.0f));
if((loopNode >= 0) && (releaseNode >= 0) && (releaseNode > loopNode))
{
@ -730,7 +761,7 @@ void EnvelopeComponent::paint(juce::Graphics& g)
if((releaseHandle != 0) && (loopHandle != 0))
{
// draw a horizontal line from release
g.setColour(colours[LoopLine]);
g.setColour(findColour(LoopLine));
const float loopY = (loopHandle->getY() + loopHandle->getBottom()) * 0.5f;
const float releaseY = (releaseHandle->getY() + releaseHandle->getBottom()) * 0.5f;
@ -748,7 +779,7 @@ void EnvelopeComponent::paint(juce::Graphics& g)
0.5f);
if(loopY == releaseY)
g.setColour(colours[LoopNode]);
g.setColour(findColour(LoopNode));
// g.drawArrow(loopX + arrowLength, releaseY,
// loopX, releaseY,
@ -770,10 +801,10 @@ inline double round(double a, double b) throw()
void EnvelopeComponent::paintBackground(juce::Graphics& g)
{
g.setColour(colours[Background]);
g.setColour(findColour(Background));
g.fillRect(0, 0, getWidth(), getHeight());
g.setColour(colours[GridLine]);
g.setColour(findColour(GridLine));
if((gridDisplayMode & GridValue) && (valueGrid > 0.0))
{
@ -904,7 +935,7 @@ void EnvelopeComponent::mouseUp(const juce::MouseEvent& e)
if(e.mods.isCtrlDown() == false)
quantiseHandle(draggingHandle);
setMouseCursor(juce::MouseCursor::CrosshairCursor);
setMouseCursor(juce::MouseCursor::DraggingHandCursor);
draggingHandle->setMousePositionToThisHandle();
draggingHandle->resetOffsets();
draggingHandle = 0;
@ -1389,28 +1420,6 @@ double EnvelopeComponent::constrainValue(double valueToConstrain) const
// return value;
//}
void EnvelopeComponent::setEnvColour(const EnvColours which, juce::Colour colour) throw()
{
if((which >= 0) && (which < NumEnvColours))
{
//lock();
colours[which] = colour;
//unlock();
//updateGUI();
getParentComponent()->repaint();
repaint();
}
}
const juce::Colour EnvelopeComponent::getEnvColour(const EnvColours which) const throw()
{
if ((which < 0) || (which >= NumEnvColours))
return juce::Colour();
else
return colours[which];
}
EnvelopeLegendComponent::EnvelopeLegendComponent(juce::String _defaultText)
: defaultText(_defaultText)
{
@ -1440,12 +1449,12 @@ void EnvelopeLegendComponent::resized()
void EnvelopeLegendComponent::paint(juce::Graphics& g)
{
EnvelopeComponent *env = getEnvelopeComponent();
juce::Colour backColour = env ? env->getEnvColour(EnvelopeComponent::LegendBackground) : juce::Colour(0xFF696969);
juce::Colour backColour = findColour(EnvelopeComponent::LegendBackground);
g.setColour(backColour);
g.fillRect(0, 0, getWidth(), getHeight());
juce::Colour textColour = env ? env->getEnvColour(EnvelopeComponent::LegendText) : juce::Colour(0xFF0000);
juce::Colour textColour = findColour(EnvelopeComponent::LegendText);
text->setColour(juce::Label::textColourId, textColour);
}

Wyświetl plik

@ -46,7 +46,7 @@
#include "EnvCurve.h"
#define HANDLESIZE 7
#define HANDLESIZE 11
#define FINETUNE 0.001
//#define MYDEBUG 1 // get rid of this later
@ -121,6 +121,7 @@ public:
private:
bool dontUpdateTimeAndValue;
void recalculatePosition();
void recalculateShouldDraw();
juce::ComponentDragger dragger;
int lastX, lastY;
@ -128,7 +129,7 @@ private:
EnvelopeHandleComponentConstrainer resizeLimits;
double time, value;
bool shouldLockTime, shouldLockValue;
bool shouldLockTime, shouldLockValue, shouldDraw;
EnvCurve curve;
bool ignoreDrag;
};
@ -235,9 +236,21 @@ public:
// double quantiseDomain(double value);
// double quantiseValue(double value);
enum EnvColours { Node, ReleaseNode, LoopNode, Line, LoopLine, Background, GridLine, LegendText, LegendBackground, NumEnvColours };
void setEnvColour(const EnvColours which, juce::Colour colour) throw();
const juce::Colour getEnvColour(const EnvColours which) const throw();
const static int COLOUR_OFFSET = 0x6082100;
enum EnvColours {
Node = COLOUR_OFFSET,
ReleaseNode = COLOUR_OFFSET + 1,
LoopNode = COLOUR_OFFSET + 2,
NodeOutline = COLOUR_OFFSET + 3,
Line = COLOUR_OFFSET + 4,
LoopLine = COLOUR_OFFSET + 5,
Background = COLOUR_OFFSET + 6,
GridLine = COLOUR_OFFSET + 7,
LegendText = COLOUR_OFFSET + 8,
LegendBackground = COLOUR_OFFSET + 9,
NumEnvColours = 10,
};
enum MoveMode { MoveClip, MoveSlide, NumMoveModes };
@ -262,8 +275,6 @@ private:
bool allowCurveEditing = false;
bool allowNodeEditing = false;
bool adsrMode = false;
juce::Colour colours[NumEnvColours];
};
class EnvelopeLegendComponent : public juce::Component
@ -311,16 +322,7 @@ public:
Env getEnv() const { return getEnvelopeComponent()->getEnv(); }
void setEnv(Env const& env) { return getEnvelopeComponent()->setEnv(env); }
float lookup(const float time) const { return getEnvelopeComponent()->lookup(time); }
void setEnvColour(const EnvelopeComponent::EnvColours which, juce::Colour const& colour) throw()
{
envelope->setEnvColour(which, colour);
}
const juce::Colour getEnvColour(const EnvelopeComponent::EnvColours which) const throw()
{
return envelope->getEnvColour(which);
}
void setDomainRange(const double min, const double max) { envelope->setDomainRange(min, max); }
void setDomainRange(const double max) { setDomainRange(0.0, max); }

Wyświetl plik

@ -1,23 +1,21 @@
#include "Effect.h"
#include <numbers>
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, const std::vector<EffectParameter*>& parameters, juce::String description) :
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, const std::vector<EffectParameter*>& parameters) :
effectApplication(effectApplication),
parameters(parameters),
enabled(nullptr),
actualValues(std::vector<double>(parameters.size(), 0.0)),
description(description) {}
actualValues(std::vector<double>(parameters.size(), 0.0)) {}
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter, juce::String description) : Effect(effectApplication, std::vector<EffectParameter*>{parameter}, description) {}
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter) : Effect(effectApplication, std::vector<EffectParameter*>{parameter}) {}
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, const std::vector<EffectParameter*>& parameters, juce::String description) :
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, const std::vector<EffectParameter*>& parameters) :
application(application),
parameters(parameters),
enabled(nullptr),
actualValues(std::vector<double>(parameters.size(), 0.0)),
description(description) {}
actualValues(std::vector<double>(parameters.size(), 0.0)) {}
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter, juce::String description) : Effect(application, std::vector<EffectParameter*>{parameter}, description) {}
Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter) : Effect(application, std::vector<EffectParameter*>{parameter}) {}
Vector2 Effect::apply(int index, Vector2 input) {
animateValues();
@ -203,7 +201,3 @@ EffectParameter* Effect::getParameter(juce::String id) {
}
return nullptr;
}
juce::String Effect::getDescription() {
return description;
}

Wyświetl plik

@ -8,10 +8,10 @@
class Effect {
public:
Effect(std::shared_ptr<EffectApplication> effectApplication, const std::vector<EffectParameter*>& parameters, juce::String description);
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter, juce::String description);
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, const std::vector<EffectParameter*>& parameters, juce::String description);
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter, juce::String description);
Effect(std::shared_ptr<EffectApplication> effectApplication, const std::vector<EffectParameter*>& parameters);
Effect(std::shared_ptr<EffectApplication> effectApplication, EffectParameter* parameter);
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, const std::vector<EffectParameter*>& parameters);
Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, EffectParameter* parameter);
Vector2 apply(int index, Vector2 input);
@ -32,7 +32,6 @@ public:
void save(juce::XmlElement* xml);
void load(juce::XmlElement* xml);
EffectParameter* getParameter(juce::String id);
juce::String getDescription();
std::vector<EffectParameter*> parameters;
BooleanParameter* enabled;
@ -44,7 +43,6 @@ private:
int precedence = -1;
int sampleRate = 192000;
std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application;
juce::String description;
std::shared_ptr<EffectApplication> effectApplication;

Wyświetl plik

@ -309,6 +309,7 @@ public:
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", getVersionHint(), 1);
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 100.0f, 0.1f, "Hz");
std::atomic<float> phase = 0.0f;
juce::String description;
std::vector<juce::AudioProcessorParameter*> getParameters() {
std::vector<juce::AudioProcessorParameter*> parameters;
@ -349,5 +350,5 @@ public:
}
}
EffectParameter(juce::String name, juce::String id, int versionHint, float value, float min, float max, float step = 0.01, bool smoothValueChange = true) : FloatParameter(name, id, versionHint, value, min, max, step), smoothValueChange(smoothValueChange) {}
EffectParameter(juce::String name, juce::String description, juce::String id, int versionHint, float value, float min, float max, float step = 0.01, bool smoothValueChange = true) : FloatParameter(name, id, versionHint, value, min, max, step), smoothValueChange(smoothValueChange), description(description) {}
};

Wyświetl plik

@ -5,6 +5,9 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, in
addAndMakeVisible(slider);
addChildComponent(lfoSlider);
addAndMakeVisible(lfo);
addAndMakeVisible(label);
label.setFont(juce::Font(13.0f));
lfo.addItem("Static", static_cast<int>(LfoType::Static));
lfo.addItem("Sine", static_cast<int>(LfoType::Sine));
@ -15,9 +18,6 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, in
lfo.addItem("Reverse Sawtooth", static_cast<int>(LfoType::ReverseSawtooth));
lfo.addItem("Noise", static_cast<int>(LfoType::Noise));
// temporarily disabling tooltips
// setTooltip(effect.getDescription());
effect.addListener(index, this);
setupComponent();
}
@ -27,6 +27,9 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect) :
void EffectComponent::setupComponent() {
EffectParameter* parameter = effect.parameters[index];
label.setTooltip(parameter->description);
label.setText(parameter->name, juce::dontSendNotification);
slider.setRange(parameter->min, parameter->max, parameter->step);
slider.setValue(parameter->getValueUnnormalised(), juce::dontSendNotification);
@ -118,16 +121,14 @@ void EffectComponent::resized() {
lfo.setBounds(bounds.removeFromRight(100).reduced(5));
}
textBounds = bounds.removeFromLeft(120);
textBounds.removeFromLeft(5);
bounds.removeFromLeft(5);
label.setBounds(bounds.removeFromLeft(120));
slider.setBounds(bounds);
lfoSlider.setBounds(bounds);
}
void EffectComponent::paint(juce::Graphics& g) {
g.fillAll(findColour(effectComponentBackgroundColourId));
g.setColour(juce::Colours::white);
g.drawText(effect.parameters[index]->name, textBounds, juce::Justification::left);
}
void EffectComponent::mouseDown(const juce::MouseEvent& event) {

Wyświetl plik

@ -28,11 +28,11 @@ public:
private:
void setupComponent();
bool lfoEnabled = true;
juce::Rectangle<int> textBounds;
std::shared_ptr<juce::Component> component;
OscirenderAudioProcessor& audioProcessor;
juce::Label popupLabel;
juce::Label label;
LabelledTextBox min{"Min"};
LabelledTextBox max{"Max"};

Wyświetl plik

@ -86,14 +86,19 @@ void EffectsListComponent::resized() {
std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectParameter* parameter) {
if (parameter->paramID == "perspectiveRotateX" || parameter->paramID == "perspectiveRotateY" || parameter->paramID == "perspectiveRotateZ") {
BooleanParameter* toggle;
juce::String axis;
if (parameter->paramID == "perspectiveRotateX") {
toggle = audioProcessor.perspectiveEffect->fixedRotateX;
axis = "X";
} else if (parameter->paramID == "perspectiveRotateY") {
toggle = audioProcessor.perspectiveEffect->fixedRotateY;
axis = "Y";
} else if (parameter->paramID == "perspectiveRotateZ") {
toggle = audioProcessor.perspectiveEffect->fixedRotateZ;
axis = "Z";
}
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, "white", "red", toggle);
button->setTooltip("Toggles whether the rotation around the " + axis + " axis is fixed, or changes according to the rotation speed.");
button->onClick = [this, toggle] {
toggle->setBoolValueNotifyingHost(!toggle->getBoolValue());
};
@ -103,6 +108,7 @@ std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectPar
std::weak_ptr<SvgButton> weakButton = button;
button->setEdgeIndent(5);
button->setToggleState(editor.editingPerspective, juce::dontSendNotification);
button->setTooltip("Toggles whether the text editor is editing the currently open file, or the Lua 3D perspective function.");
button->onClick = [this, weakButton] {
if (auto button = weakButton.lock()) {
editor.editPerspectiveFunction(button->getToggleState());