kopia lustrzana https://github.com/jameshball/osci-render
Merge pull request #27 from jameshball/lua
Add support for .lua files with .lua specific settingspull/170/head
commit
b29a24e13b
|
@ -1,20 +0,0 @@
|
||||||
#include "EffectComponentGroup.h"
|
|
||||||
|
|
||||||
EffectComponentGroup::EffectComponentGroup(const juce::String& id, const juce::String& name) : id(id) {
|
|
||||||
addAndMakeVisible(slider);
|
|
||||||
addAndMakeVisible(label);
|
|
||||||
|
|
||||||
label.setText(name, juce::dontSendNotification);
|
|
||||||
label.attachToComponent(&slider, true);
|
|
||||||
|
|
||||||
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
|
||||||
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
EffectComponentGroup::~EffectComponentGroup() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void EffectComponentGroup::resized() {
|
|
||||||
auto sliderLeft = 100;
|
|
||||||
slider.setBounds(sliderLeft, 0, getWidth() - 200, 20);
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
|
||||||
|
|
||||||
class EffectComponentGroup : public juce::Component {
|
|
||||||
public:
|
|
||||||
EffectComponentGroup(const juce::String& id, const juce::String& name);
|
|
||||||
~EffectComponentGroup() override;
|
|
||||||
|
|
||||||
void resized() override;
|
|
||||||
|
|
||||||
juce::Slider slider;
|
|
||||||
juce::Label label;
|
|
||||||
juce::String id;
|
|
||||||
|
|
||||||
private:
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponentGroup)
|
|
||||||
};
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p) : audioProcessor
|
||||||
setText("Audio Effects");
|
setText("Audio Effects");
|
||||||
|
|
||||||
addAndMakeVisible(frequency);
|
addAndMakeVisible(frequency);
|
||||||
|
frequency.setHideCheckbox(true);
|
||||||
|
|
||||||
frequency.slider.setRange(0.0, 12000.0);
|
|
||||||
frequency.slider.setSkewFactorFromMidPoint(500.0);
|
frequency.slider.setSkewFactorFromMidPoint(500.0);
|
||||||
frequency.slider.setTextValueSuffix("Hz");
|
frequency.slider.setTextValueSuffix("Hz");
|
||||||
frequency.slider.setValue(audioProcessor.frequency, juce::dontSendNotification);
|
frequency.slider.setValue(audioProcessor.frequency, juce::dontSendNotification);
|
||||||
|
@ -43,13 +43,8 @@ EffectsComponent::~EffectsComponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectsComponent::resized() {
|
void EffectsComponent::resized() {
|
||||||
auto xPadding = 10;
|
|
||||||
auto yPadding = 20;
|
|
||||||
frequency.setBounds(xPadding, yPadding, getWidth() - xPadding, 40);
|
|
||||||
|
|
||||||
auto area = getLocalBounds().reduced(20);
|
auto area = getLocalBounds().reduced(20);
|
||||||
auto row = area.removeFromTop(24);
|
frequency.setBounds(area.removeFromTop(30));
|
||||||
addBtn.setBounds(row.removeFromRight(100));
|
|
||||||
|
|
||||||
area.removeFromTop(6);
|
area.removeFromTop(6);
|
||||||
listBox.setBounds(area);
|
listBox.setBounds(area);
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
#include "audio/BitCrushEffect.h"
|
#include "audio/BitCrushEffect.h"
|
||||||
#include "EffectComponentGroup.h"
|
|
||||||
#include "PluginProcessor.h"
|
#include "PluginProcessor.h"
|
||||||
#include "components/DraggableListBox.h"
|
#include "components/DraggableListBox.h"
|
||||||
#include "components/MyListComponent.h"
|
#include "components/EffectsListComponent.h"
|
||||||
|
|
||||||
class EffectsComponent : public juce::GroupComponent {
|
class EffectsComponent : public juce::GroupComponent {
|
||||||
public:
|
public:
|
||||||
|
@ -17,13 +16,13 @@ public:
|
||||||
private:
|
private:
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
|
||||||
juce::TextButton addBtn;
|
// juce::TextButton addBtn;
|
||||||
|
|
||||||
MyListBoxItemData itemData;
|
AudioEffectListBoxItemData itemData;
|
||||||
MyListBoxModel listBoxModel;
|
EffectsListBoxModel listBoxModel;
|
||||||
DraggableListBox listBox;
|
DraggableListBox listBox;
|
||||||
|
|
||||||
EffectComponentGroup frequency = EffectComponentGroup("frequency", "Frequency");
|
EffectComponent frequency = EffectComponent(0.0, 12000.0, 0.1, 400, "Frequency", "frequency");
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent)
|
||||||
};
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "LuaComponent.h"
|
||||||
|
#include "PluginEditor.h"
|
||||||
|
|
||||||
|
LuaComponent::LuaComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), pluginEditor(editor), slidersModel(sliders, p) {
|
||||||
|
setText(".lua File Settings");
|
||||||
|
|
||||||
|
sliders.setModel(&slidersModel);
|
||||||
|
sliders.setRowHeight(30);
|
||||||
|
addAndMakeVisible(sliders);
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaComponent::~LuaComponent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaComponent::resized() {
|
||||||
|
auto area = getLocalBounds().reduced(20);
|
||||||
|
sliders.setBounds(area);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
#include "components/LuaListComponent.h"
|
||||||
|
|
||||||
|
class OscirenderAudioProcessorEditor;
|
||||||
|
class LuaComponent : public juce::GroupComponent {
|
||||||
|
public:
|
||||||
|
LuaComponent(OscirenderAudioProcessor&, OscirenderAudioProcessorEditor&);
|
||||||
|
~LuaComponent() override;
|
||||||
|
|
||||||
|
void resized() override;
|
||||||
|
private:
|
||||||
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
OscirenderAudioProcessorEditor& pluginEditor;
|
||||||
|
|
||||||
|
LuaListBoxModel slidersModel;
|
||||||
|
juce::ListBox sliders;
|
||||||
|
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LuaComponent)
|
||||||
|
};
|
|
@ -20,6 +20,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
||||||
audioProcessor.addFile(file);
|
audioProcessor.addFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pluginEditor.addCodeEditor(audioProcessor.getCurrentFileIndex());
|
||||||
pluginEditor.updateCodeEditor();
|
pluginEditor.updateCodeEditor();
|
||||||
updateFileLabel();
|
updateFileLabel();
|
||||||
});
|
});
|
||||||
|
@ -29,6 +30,11 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
||||||
closeFileButton.setButtonText("Close File");
|
closeFileButton.setButtonText("Close File");
|
||||||
|
|
||||||
closeFileButton.onClick = [this] {
|
closeFileButton.onClick = [this] {
|
||||||
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
|
if (index == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pluginEditor.removeCodeEditor(audioProcessor.getCurrentFileIndex());
|
||||||
audioProcessor.removeFile(audioProcessor.getCurrentFileIndex());
|
audioProcessor.removeFile(audioProcessor.getCurrentFileIndex());
|
||||||
pluginEditor.updateCodeEditor();
|
pluginEditor.updateCodeEditor();
|
||||||
updateFileLabel();
|
updateFileLabel();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
#include "EffectComponentGroup.h"
|
|
||||||
#include "PluginProcessor.h"
|
#include "PluginProcessor.h"
|
||||||
#include "parser/FileParser.h"
|
#include "parser/FileParser.h"
|
||||||
#include "parser/FrameProducer.h"
|
#include "parser/FrameProducer.h"
|
||||||
|
@ -13,6 +12,7 @@ public:
|
||||||
~MainComponent() override;
|
~MainComponent() override;
|
||||||
|
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
void updateFileLabel();
|
||||||
private:
|
private:
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
OscirenderAudioProcessorEditor& pluginEditor;
|
OscirenderAudioProcessorEditor& pluginEditor;
|
||||||
|
@ -22,7 +22,5 @@ private:
|
||||||
juce::TextButton closeFileButton;
|
juce::TextButton closeFileButton;
|
||||||
juce::Label fileLabel;
|
juce::Label fileLabel;
|
||||||
|
|
||||||
void updateFileLabel();
|
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
|
||||||
};
|
};
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p)
|
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p)
|
||||||
: AudioProcessorEditor(&p), audioProcessor(p), effects(p), main(p, *this), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white)
|
: AudioProcessorEditor(&p), audioProcessor(p), effects(p), main(p, *this), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white), lua(p, *this)
|
||||||
{
|
{
|
||||||
// Make sure that before the constructor has finished, you've set the
|
// Make sure that before the constructor has finished, you've set the
|
||||||
// editor's size to whatever you need it to be.
|
// editor's size to whatever you need it to be.
|
||||||
|
@ -20,50 +20,31 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
||||||
|
|
||||||
addAndMakeVisible(effects);
|
addAndMakeVisible(effects);
|
||||||
addAndMakeVisible(main);
|
addAndMakeVisible(main);
|
||||||
|
addAndMakeVisible(lua);
|
||||||
codeEditor = std::make_unique<juce::CodeEditorComponent>(codeDocument, &luaTokeniser);
|
|
||||||
addAndMakeVisible(*codeEditor);
|
|
||||||
|
|
||||||
codeEditor->loadContent (R"LUA(
|
|
||||||
-- defines a factorial function
|
|
||||||
function fact (n)
|
|
||||||
if n == 0 then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return n * fact(n-1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
print("enter a number:")
|
|
||||||
a = io.read("*number") -- read a number
|
|
||||||
print(fact(a))
|
|
||||||
)LUA");
|
|
||||||
|
|
||||||
// I need to disable accessibility otherwise it doesn't work! Appears to be a JUCE issue, very annoying!
|
|
||||||
codeEditor->setAccessible(false);
|
|
||||||
|
|
||||||
// listen for changes to the code editor
|
|
||||||
codeDocument.addListener(this);
|
|
||||||
|
|
||||||
addAndMakeVisible(collapseButton);
|
addAndMakeVisible(collapseButton);
|
||||||
collapseButton.onClick = [this] {
|
collapseButton.onClick = [this] {
|
||||||
if (codeEditor->isVisible()) {
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
codeEditor->setVisible(false);
|
if (index != -1) {
|
||||||
juce::Path path;
|
if (codeEditors[index]->isVisible()) {
|
||||||
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
codeEditors[index]->setVisible(false);
|
||||||
collapseButton.setShape(path, false, true, true);
|
juce::Path path;
|
||||||
} else {
|
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
||||||
codeEditor->setVisible(true);
|
collapseButton.setShape(path, false, true, true);
|
||||||
updateCodeEditor();
|
} else {
|
||||||
juce::Path path;
|
codeEditors[index]->setVisible(true);
|
||||||
path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
updateCodeEditor();
|
||||||
collapseButton.setShape(path, false, true, true);
|
juce::Path path;
|
||||||
}
|
path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
||||||
resized();
|
collapseButton.setShape(path, false, true, true);
|
||||||
|
}
|
||||||
|
resized();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
juce::Path path;
|
juce::Path path;
|
||||||
path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
||||||
collapseButton.setShape(path, false, true, true);
|
collapseButton.setShape(path, false, true, true);
|
||||||
|
resized();
|
||||||
}
|
}
|
||||||
|
|
||||||
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {}
|
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {}
|
||||||
|
@ -80,54 +61,102 @@ void OscirenderAudioProcessorEditor::paint (juce::Graphics& g)
|
||||||
void OscirenderAudioProcessorEditor::resized() {
|
void OscirenderAudioProcessorEditor::resized() {
|
||||||
auto area = getLocalBounds();
|
auto area = getLocalBounds();
|
||||||
auto sections = 2;
|
auto sections = 2;
|
||||||
if (codeEditor != nullptr) {
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
if (codeEditor->isVisible()) {
|
if (index != -1) {
|
||||||
|
if (codeEditors[index]->isVisible()) {
|
||||||
sections++;
|
sections++;
|
||||||
codeEditor->setBounds(area.removeFromRight(getWidth() / sections));
|
codeEditors[index]->setBounds(area.removeFromRight(getWidth() / sections));
|
||||||
} else {
|
} else {
|
||||||
codeEditor->setBounds(0, 0, 0, 0);
|
codeEditors[index]->setBounds(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
collapseButton.setBounds(area.removeFromRight(20));
|
collapseButton.setBounds(area.removeFromRight(20));
|
||||||
}
|
} else {
|
||||||
|
collapseButton.setBounds(0, 0, 0, 0);
|
||||||
|
}
|
||||||
effects.setBounds(area.removeFromRight(getWidth() / sections));
|
effects.setBounds(area.removeFromRight(getWidth() / sections));
|
||||||
main.setBounds(area.removeFromTop(getHeight() / 2));
|
main.setBounds(area.removeFromTop(getHeight() / 2));
|
||||||
|
lua.setBounds(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OscirenderAudioProcessorEditor::addCodeEditor(int index) {
|
||||||
|
std::shared_ptr<juce::CodeDocument> codeDocument = std::make_shared<juce::CodeDocument>();
|
||||||
|
codeDocuments.insert(codeDocuments.begin() + index, codeDocument);
|
||||||
|
juce::String extension = audioProcessor.getFile(index).getFileExtension();
|
||||||
|
juce::CodeTokeniser* tokeniser = nullptr;
|
||||||
|
if (extension == ".lua") {
|
||||||
|
tokeniser = &luaTokeniser;
|
||||||
|
} else if (extension == ".svg") {
|
||||||
|
tokeniser = &xmlTokeniser;
|
||||||
|
}
|
||||||
|
std::shared_ptr<juce::CodeEditorComponent> editor = std::make_shared<juce::CodeEditorComponent>(*codeDocument, tokeniser);
|
||||||
|
// I need to disable accessibility otherwise it doesn't work! Appears to be a JUCE issue, very annoying!
|
||||||
|
editor->setAccessible(false);
|
||||||
|
// listen for changes to the code editor
|
||||||
|
codeDocument->addListener(this);
|
||||||
|
codeEditors.insert(codeEditors.begin() + index, editor);
|
||||||
|
addChildComponent(*editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OscirenderAudioProcessorEditor::removeCodeEditor(int index) {
|
||||||
|
codeEditors.erase(codeEditors.begin() + index);
|
||||||
|
codeDocuments.erase(codeDocuments.begin() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessorEditor::updateCodeEditor() {
|
void OscirenderAudioProcessorEditor::updateCodeEditor() {
|
||||||
if (codeEditor->isVisible() && audioProcessor.getCurrentFileIndex() != -1) {
|
// check if any code editors are visible
|
||||||
codeEditor->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(audioProcessor.getCurrentFileIndex()), false).readEntireStreamAsString());
|
bool visible = false;
|
||||||
|
for (int i = 0; i < codeEditors.size(); i++) {
|
||||||
|
if (codeEditors[i]->isVisible()) {
|
||||||
|
visible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
|
if (index != -1 && visible) {
|
||||||
|
for (int i = 0; i < codeEditors.size(); i++) {
|
||||||
|
codeEditors[i]->setVisible(false);
|
||||||
|
}
|
||||||
|
codeEditors[index]->setVisible(true);
|
||||||
|
codeEditors[index]->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(index), false).readEntireStreamAsString());
|
||||||
}
|
}
|
||||||
|
resized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessorEditor::codeDocumentTextInserted(const juce::String& newText, int insertIndex) {
|
void OscirenderAudioProcessorEditor::codeDocumentTextInserted(const juce::String& newText, int insertIndex) {
|
||||||
juce::String file = codeDocument.getAllContent();
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
audioProcessor.updateFileBlock(audioProcessor.getCurrentFileIndex(), std::make_shared<juce::MemoryBlock>(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1));
|
juce::String file = codeDocuments[index]->getAllContent();
|
||||||
|
audioProcessor.updateFileBlock(index, std::make_shared<juce::MemoryBlock>(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessorEditor::codeDocumentTextDeleted(int startIndex, int endIndex) {
|
void OscirenderAudioProcessorEditor::codeDocumentTextDeleted(int startIndex, int endIndex) {
|
||||||
juce::String file = codeDocument.getAllContent();
|
int index = audioProcessor.getCurrentFileIndex();
|
||||||
audioProcessor.updateFileBlock(audioProcessor.getCurrentFileIndex(), std::make_shared<juce::MemoryBlock>(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1));
|
juce::String file = codeDocuments[index]->getAllContent();
|
||||||
|
audioProcessor.updateFileBlock(index, std::make_shared<juce::MemoryBlock>(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OscirenderAudioProcessorEditor::keyPressed(const juce::KeyPress& key) {
|
bool OscirenderAudioProcessorEditor::keyPressed(const juce::KeyPress& key) {
|
||||||
int numFiles = audioProcessor.numFiles();
|
int numFiles = audioProcessor.numFiles();
|
||||||
int currentFile = audioProcessor.getCurrentFileIndex();
|
int currentFile = audioProcessor.getCurrentFileIndex();
|
||||||
|
bool updated = false;
|
||||||
if (key.getTextCharacter() == 'j') {
|
if (key.getTextCharacter() == 'j') {
|
||||||
currentFile++;
|
currentFile++;
|
||||||
if (currentFile == numFiles) {
|
if (currentFile == numFiles) {
|
||||||
currentFile = 0;
|
currentFile = 0;
|
||||||
}
|
}
|
||||||
audioProcessor.changeCurrentFile(currentFile);
|
updated = true;
|
||||||
updateCodeEditor();
|
|
||||||
return true;
|
|
||||||
} else if (key.getTextCharacter() == 'k') {
|
} else if (key.getTextCharacter() == 'k') {
|
||||||
currentFile--;
|
currentFile--;
|
||||||
if (currentFile < 0) {
|
if (currentFile < 0) {
|
||||||
currentFile = numFiles - 1;
|
currentFile = numFiles - 1;
|
||||||
}
|
}
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
audioProcessor.changeCurrentFile(currentFile);
|
audioProcessor.changeCurrentFile(currentFile);
|
||||||
updateCodeEditor();
|
updateCodeEditor();
|
||||||
return true;
|
main.updateFileLabel();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
#include "PluginProcessor.h"
|
#include "PluginProcessor.h"
|
||||||
#include "EffectComponentGroup.h"
|
|
||||||
#include "EffectsComponent.h"
|
#include "EffectsComponent.h"
|
||||||
#include "MainComponent.h"
|
#include "MainComponent.h"
|
||||||
|
#include "LuaComponent.h"
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
|
@ -27,15 +27,19 @@ public:
|
||||||
void paint (juce::Graphics&) override;
|
void paint (juce::Graphics&) override;
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
|
void addCodeEditor(int index);
|
||||||
|
void removeCodeEditor(int index);
|
||||||
void updateCodeEditor();
|
void updateCodeEditor();
|
||||||
private:
|
private:
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
|
||||||
MainComponent main;
|
MainComponent main;
|
||||||
|
LuaComponent lua;
|
||||||
EffectsComponent effects;
|
EffectsComponent effects;
|
||||||
juce::CodeDocument codeDocument;
|
std::vector<std::shared_ptr<juce::CodeDocument>> codeDocuments;
|
||||||
|
std::vector<std::shared_ptr<juce::CodeEditorComponent>> codeEditors;
|
||||||
juce::LuaTokeniser luaTokeniser;
|
juce::LuaTokeniser luaTokeniser;
|
||||||
std::unique_ptr<juce::CodeEditorComponent> codeEditor;
|
juce::XmlTokeniser xmlTokeniser;
|
||||||
juce::ShapeButton collapseButton;
|
juce::ShapeButton collapseButton;
|
||||||
|
|
||||||
void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override;
|
void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override;
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "audio/VectorCancellingEffect.h"
|
#include "audio/VectorCancellingEffect.h"
|
||||||
#include "audio/DistortEffect.h"
|
#include "audio/DistortEffect.h"
|
||||||
#include "audio/SmoothEffect.h"
|
#include "audio/SmoothEffect.h"
|
||||||
|
#include "audio/BitCrushEffect.h"
|
||||||
|
#include "audio/BulgeEffect.h"
|
||||||
|
#include "audio/LuaEffect.h"
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
OscirenderAudioProcessor::OscirenderAudioProcessor()
|
OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
|
@ -38,6 +41,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(true), "Vertical shift", "verticalDistort"));
|
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(true), "Vertical shift", "verticalDistort"));
|
||||||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(false), "Horizontal shift", "horizontalDistort"));
|
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(false), "Horizontal shift", "horizontalDistort"));
|
||||||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<SmoothEffect>(), "Smoothing", "smoothing"));
|
allEffects.push_back(std::make_shared<Effect>(std::make_unique<SmoothEffect>(), "Smoothing", "smoothing"));
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
addLuaSlider();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OscirenderAudioProcessor::~OscirenderAudioProcessor()
|
OscirenderAudioProcessor::~OscirenderAudioProcessor()
|
||||||
|
@ -145,6 +152,26 @@ bool OscirenderAudioProcessor::isBusesLayoutSupported (const BusesLayout& layout
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void OscirenderAudioProcessor::addLuaSlider() {
|
||||||
|
juce::String sliderName = "";
|
||||||
|
|
||||||
|
int sliderNum = luaEffects.size() + 1;
|
||||||
|
while (sliderNum > 0) {
|
||||||
|
int mod = (sliderNum - 1) % 26;
|
||||||
|
sliderName = (char)(mod + 'A') + sliderName;
|
||||||
|
sliderNum = (sliderNum - mod) / 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaEffects.push_back(std::make_shared<Effect>(std::make_unique<LuaEffect>(sliderName, *this), "Lua " + sliderName, "lua" + sliderName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OscirenderAudioProcessor::updateLuaValues() {
|
||||||
|
Vector2 vector;
|
||||||
|
for (auto& effect : luaEffects) {
|
||||||
|
effect->apply(0, vector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessor::updateAngleDelta() {
|
void OscirenderAudioProcessor::updateAngleDelta() {
|
||||||
auto cyclesPerSample = frequency / currentSampleRate;
|
auto cyclesPerSample = frequency / currentSampleRate;
|
||||||
thetaDelta = cyclesPerSample * 2.0 * juce::MathConstants<double>::pi;
|
thetaDelta = cyclesPerSample * 2.0 * juce::MathConstants<double>::pi;
|
||||||
|
@ -238,9 +265,14 @@ void OscirenderAudioProcessor::openFile(int index) {
|
||||||
producer->setSource(parsers[index], index);
|
producer->setSource(parsers[index], index);
|
||||||
currentFile = index;
|
currentFile = index;
|
||||||
invalidateFrameBuffer = true;
|
invalidateFrameBuffer = true;
|
||||||
|
updateLuaValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessor::changeCurrentFile(int index) {
|
void OscirenderAudioProcessor::changeCurrentFile(int index) {
|
||||||
|
if (index == -1) {
|
||||||
|
currentFile = -1;
|
||||||
|
producer->setSource(std::make_shared<FileParser>(), -1);
|
||||||
|
}
|
||||||
if (index < 0 || index >= fileBlocks.size()) {
|
if (index < 0 || index >= fileBlocks.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -253,10 +285,18 @@ int OscirenderAudioProcessor::getCurrentFileIndex() {
|
||||||
return currentFile;
|
return currentFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<FileParser> OscirenderAudioProcessor::getCurrentFileParser() {
|
||||||
|
return parsers[currentFile];
|
||||||
|
}
|
||||||
|
|
||||||
juce::File OscirenderAudioProcessor::getCurrentFile() {
|
juce::File OscirenderAudioProcessor::getCurrentFile() {
|
||||||
return files[currentFile];
|
return files[currentFile];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
juce::File OscirenderAudioProcessor::getFile(int index) {
|
||||||
|
return files[index];
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<juce::MemoryBlock> OscirenderAudioProcessor::getFileBlock(int index) {
|
std::shared_ptr<juce::MemoryBlock> OscirenderAudioProcessor::getFileBlock(int index) {
|
||||||
return fileBlocks[index];
|
return fileBlocks[index];
|
||||||
}
|
}
|
||||||
|
@ -300,7 +340,9 @@ void OscirenderAudioProcessor::updateFrame() {
|
||||||
|
|
||||||
frameLength = Shape::totalLength(frame);
|
frameLength = Shape::totalLength(frame);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
DBG("frame not ready!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscirenderAudioProcessor::updateLengthIncrement() {
|
void OscirenderAudioProcessor::updateLengthIncrement() {
|
||||||
|
@ -345,7 +387,11 @@ void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, j
|
||||||
double y = 0.0;
|
double y = 0.0;
|
||||||
double length = 0.0;
|
double length = 0.0;
|
||||||
|
|
||||||
if (currentShape < frame.size()) {
|
bool renderingSample = currentFile >= 0 && parsers[currentFile]->isSample();
|
||||||
|
|
||||||
|
if (renderingSample) {
|
||||||
|
channels = parsers[currentFile]->nextSample();
|
||||||
|
} else if (currentShape < frame.size()) {
|
||||||
auto& shape = frame[currentShape];
|
auto& shape = frame[currentShape];
|
||||||
length = shape->length();
|
length = shape->length();
|
||||||
double drawingProgress = length == 0.0 ? 1 : shapeDrawn / length;
|
double drawingProgress = length == 0.0 ? 1 : shapeDrawn / length;
|
||||||
|
@ -361,6 +407,7 @@ void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, j
|
||||||
x = channels.x;
|
x = channels.x;
|
||||||
y = channels.y;
|
y = channels.y;
|
||||||
|
|
||||||
|
|
||||||
if (totalNumOutputChannels >= 2) {
|
if (totalNumOutputChannels >= 2) {
|
||||||
channelData[0][sample] = x;
|
channelData[0][sample] = x;
|
||||||
channelData[1][sample] = y;
|
channelData[1][sample] = y;
|
||||||
|
@ -368,29 +415,31 @@ void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, j
|
||||||
channelData[0][sample] = x;
|
channelData[0][sample] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hard cap on how many times it can be over the length to
|
if (!renderingSample) {
|
||||||
// prevent audio stuttering
|
// hard cap on how many times it can be over the length to
|
||||||
frameDrawn += std::min(lengthIncrement, 20 * length);
|
// prevent audio stuttering
|
||||||
shapeDrawn += std::min(lengthIncrement, 20 * length);
|
frameDrawn += std::min(lengthIncrement, 20 * length);
|
||||||
|
shapeDrawn += std::min(lengthIncrement, 20 * length);
|
||||||
|
|
||||||
// Need to skip all shapes that the lengthIncrement draws over.
|
// Need to skip all shapes that the lengthIncrement draws over.
|
||||||
// This is especially an issue when there are lots of small lines being
|
// This is especially an issue when there are lots of small lines being
|
||||||
// drawn.
|
// drawn.
|
||||||
while (shapeDrawn > length) {
|
while (shapeDrawn > length) {
|
||||||
shapeDrawn -= length;
|
shapeDrawn -= length;
|
||||||
currentShape++;
|
currentShape++;
|
||||||
if (currentShape >= frame.size()) {
|
if (currentShape >= frame.size()) {
|
||||||
currentShape = 0;
|
currentShape = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// POTENTIAL TODO: Think of a way to make this more efficient when iterating
|
// POTENTIAL TODO: Think of a way to make this more efficient when iterating
|
||||||
// this loop many times
|
// this loop many times
|
||||||
length = frame[currentShape]->len;
|
length = frame[currentShape]->len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (frameDrawn >= frameLength) {
|
if (!renderingSample && frameDrawn >= frameLength) {
|
||||||
updateFrame();
|
updateFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::MidiBuffer processedMidi;
|
juce::MidiBuffer processedMidi;
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
#include "parser/FrameProducer.h"
|
#include "parser/FrameProducer.h"
|
||||||
#include "parser/FrameConsumer.h"
|
#include "parser/FrameConsumer.h"
|
||||||
#include "audio/Effect.h"
|
#include "audio/Effect.h"
|
||||||
#include "audio/BitCrushEffect.h"
|
|
||||||
#include "audio/BulgeEffect.h"
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
|
@ -72,8 +70,7 @@ public:
|
||||||
std::vector<std::shared_ptr<Effect>> allEffects;
|
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||||
std::shared_ptr<std::vector<std::shared_ptr<Effect>>> enabledEffects = std::make_shared<std::vector<std::shared_ptr<Effect>>>();
|
std::shared_ptr<std::vector<std::shared_ptr<Effect>>> enabledEffects = std::make_shared<std::vector<std::shared_ptr<Effect>>>();
|
||||||
|
|
||||||
BitCrushEffect bitCrushEffect = BitCrushEffect();
|
std::vector<std::shared_ptr<Effect>> luaEffects;
|
||||||
BulgeEffect bulgeEffect = BulgeEffect();
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<FileParser>> parsers;
|
std::vector<std::shared_ptr<FileParser>> parsers;
|
||||||
std::vector<std::shared_ptr<juce::MemoryBlock>> fileBlocks;
|
std::vector<std::shared_ptr<juce::MemoryBlock>> fileBlocks;
|
||||||
|
@ -82,6 +79,8 @@ public:
|
||||||
|
|
||||||
std::unique_ptr<FrameProducer> producer;
|
std::unique_ptr<FrameProducer> producer;
|
||||||
|
|
||||||
|
void addLuaSlider();
|
||||||
|
void updateLuaValues();
|
||||||
void updateAngleDelta();
|
void updateAngleDelta();
|
||||||
void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override;
|
void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override;
|
||||||
void enableEffect(std::shared_ptr<Effect> effect);
|
void enableEffect(std::shared_ptr<Effect> effect);
|
||||||
|
@ -94,7 +93,9 @@ public:
|
||||||
void openFile(int index);
|
void openFile(int index);
|
||||||
void changeCurrentFile(int index);
|
void changeCurrentFile(int index);
|
||||||
int getCurrentFileIndex();
|
int getCurrentFileIndex();
|
||||||
|
std::shared_ptr<FileParser> getCurrentFileParser();
|
||||||
juce::File getCurrentFile();
|
juce::File getCurrentFile();
|
||||||
|
juce::File getFile(int index);
|
||||||
std::shared_ptr<juce::MemoryBlock> getFileBlock(int index);
|
std::shared_ptr<juce::MemoryBlock> getFileBlock(int index);
|
||||||
private:
|
private:
|
||||||
double theta = 0.0;
|
double theta = 0.0;
|
||||||
|
@ -115,6 +116,7 @@ private:
|
||||||
|
|
||||||
void updateFrame();
|
void updateFrame();
|
||||||
void updateLengthIncrement();
|
void updateLengthIncrement();
|
||||||
|
void syncLuaSliders();
|
||||||
|
|
||||||
const double MIN_LENGTH_INCREMENT = 0.000001;
|
const double MIN_LENGTH_INCREMENT = 0.000001;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "LuaEffect.h"
|
||||||
|
#include "../lua/LuaParser.h"
|
||||||
|
|
||||||
|
Vector2 LuaEffect::apply(int index, Vector2 input, double value, double frequency, double sampleRate) {
|
||||||
|
int fileIndex = audioProcessor.getCurrentFileIndex();
|
||||||
|
if (fileIndex == -1) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
std::shared_ptr<LuaParser> parser = audioProcessor.getCurrentFileParser()->getLua();
|
||||||
|
if (parser != nullptr) {
|
||||||
|
parser->setVariable("slider_" + name.toLowerCase(), value);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
#include "EffectApplication.h"
|
||||||
|
#include "../shape/Vector2.h"
|
||||||
|
#include "../audio/Effect.h"
|
||||||
|
#include "../PluginProcessor.h"
|
||||||
|
|
||||||
|
class LuaEffect : public EffectApplication {
|
||||||
|
public:
|
||||||
|
LuaEffect(juce::String name, OscirenderAudioProcessor& p) : audioProcessor(p), name(name) {};
|
||||||
|
|
||||||
|
Vector2 apply(int index, Vector2 input, double value, double frequency, double sampleRate) override;
|
||||||
|
private:
|
||||||
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
juce::String name;
|
||||||
|
};
|
|
@ -4,8 +4,6 @@ DraggableListBoxItemData::~DraggableListBoxItemData() {};
|
||||||
|
|
||||||
void DraggableListBoxItem::paint(juce::Graphics& g)
|
void DraggableListBoxItem::paint(juce::Graphics& g)
|
||||||
{
|
{
|
||||||
modelData.paintContents(rowNum, g, getLocalBounds());
|
|
||||||
|
|
||||||
if (insertAfter)
|
if (insertAfter)
|
||||||
{
|
{
|
||||||
g.setColour(juce::Colours::red);
|
g.setColour(juce::Colours::red);
|
||||||
|
|
|
@ -8,7 +8,6 @@ struct DraggableListBoxItemData
|
||||||
virtual ~DraggableListBoxItemData() = 0;
|
virtual ~DraggableListBoxItemData() = 0;
|
||||||
|
|
||||||
virtual int getNumItems() = 0;
|
virtual int getNumItems() = 0;
|
||||||
virtual void paintContents(int, juce::Graphics&, juce::Rectangle<int>) = 0;
|
|
||||||
|
|
||||||
virtual void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) = 0;
|
virtual void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) = 0;
|
||||||
virtual void moveAfter(int indexOfItemToMove, int indexOfItemToPlaceAfter) = 0;
|
virtual void moveAfter(int indexOfItemToMove, int indexOfItemToPlaceAfter) = 0;
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "EffectComponent.h"
|
||||||
|
|
||||||
|
EffectComponent::EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id) : name(name), id(id) {
|
||||||
|
componentSetup();
|
||||||
|
slider.setRange(min, max, step);
|
||||||
|
slider.setValue(value, juce::dontSendNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect) : name(effect.getName()), id(effect.getId()) {
|
||||||
|
componentSetup();
|
||||||
|
slider.setRange(min, max, step);
|
||||||
|
slider.setValue(effect.getValue(), juce::dontSendNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectComponent::componentSetup() {
|
||||||
|
addAndMakeVisible(slider);
|
||||||
|
addAndMakeVisible(selected);
|
||||||
|
|
||||||
|
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
||||||
|
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
||||||
|
|
||||||
|
selected.setToggleState(false, juce::dontSendNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EffectComponent::~EffectComponent() {}
|
||||||
|
|
||||||
|
void EffectComponent::resized() {
|
||||||
|
auto sliderRight = getWidth() - 140;
|
||||||
|
auto bounds = getLocalBounds();
|
||||||
|
bounds.removeFromRight(10);
|
||||||
|
slider.setBounds(bounds.removeFromRight(sliderRight));
|
||||||
|
if (hideCheckbox) {
|
||||||
|
bounds.removeFromLeft(5);
|
||||||
|
} else {
|
||||||
|
bounds.removeFromLeft(2);
|
||||||
|
selected.setBounds(bounds.removeFromLeft(25));
|
||||||
|
}
|
||||||
|
textBounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectComponent::paint(juce::Graphics& g) {
|
||||||
|
g.fillAll(juce::Colours::lightgrey);
|
||||||
|
g.setColour(juce::Colours::black);
|
||||||
|
auto bounds = getLocalBounds();
|
||||||
|
g.drawRect(bounds);
|
||||||
|
g.drawText(name, textBounds, juce::Justification::left);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectComponent::setHideCheckbox(bool hide) {
|
||||||
|
hideCheckbox = hide;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "../PluginProcessor.h"
|
||||||
|
#include "../audio/Effect.h"
|
||||||
|
|
||||||
|
|
||||||
|
class EffectComponent : public juce::Component {
|
||||||
|
public:
|
||||||
|
EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id);
|
||||||
|
EffectComponent(double min, double max, double step, Effect& effect);
|
||||||
|
~EffectComponent();
|
||||||
|
|
||||||
|
void resized() override;
|
||||||
|
void paint(juce::Graphics& g) override;
|
||||||
|
|
||||||
|
void setHideCheckbox(bool hide);
|
||||||
|
|
||||||
|
juce::Slider slider;
|
||||||
|
juce::String id;
|
||||||
|
juce::String name;
|
||||||
|
juce::ToggleButton selected;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void componentSetup();
|
||||||
|
bool hideCheckbox = false;
|
||||||
|
juce::Rectangle<int> textBounds;
|
||||||
|
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponent)
|
||||||
|
};
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "EffectsListComponent.h"
|
||||||
|
|
||||||
|
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<EffectComponent> effectComponent) : DraggableListBoxItem(lb, data, rn), effectComponent(effectComponent) {
|
||||||
|
addAndMakeVisible(*effectComponent);
|
||||||
|
|
||||||
|
effectComponent->slider.setValue(data.getValue(rn), juce::dontSendNotification);
|
||||||
|
effectComponent->slider.onValueChange = [this] {
|
||||||
|
((AudioEffectListBoxItemData&)modelData).setValue(rowNum, this->effectComponent->slider.getValue());
|
||||||
|
};
|
||||||
|
|
||||||
|
// check if effect is in audioProcessor enabled effects
|
||||||
|
bool isSelected = false;
|
||||||
|
for (auto effect : *data.audioProcessor.enabledEffects) {
|
||||||
|
if (effect->getId() == data.getId(rn)) {
|
||||||
|
isSelected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
||||||
|
effectComponent->selected.onClick = [this] {
|
||||||
|
((AudioEffectListBoxItemData&)modelData).setSelected(rowNum, this->effectComponent->selected.getToggleState());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectsListComponent::~EffectsListComponent() {}
|
||||||
|
|
||||||
|
void EffectsListComponent::paint(juce::Graphics& g) {
|
||||||
|
DraggableListBoxItem::paint(g);
|
||||||
|
auto bounds = getLocalBounds();
|
||||||
|
bounds.removeFromLeft(20);
|
||||||
|
// draw drag and drop handle using circles
|
||||||
|
g.setColour(juce::Colours::white);
|
||||||
|
double size = 4;
|
||||||
|
double leftPad = 4;
|
||||||
|
double spacing = 7;
|
||||||
|
double topPad = 7;
|
||||||
|
g.fillEllipse(leftPad, topPad, size, size);
|
||||||
|
g.fillEllipse(leftPad, topPad + spacing, size, size);
|
||||||
|
g.fillEllipse(leftPad, topPad + 2 * spacing, size, size);
|
||||||
|
g.fillEllipse(leftPad + spacing, topPad, size, size);
|
||||||
|
g.fillEllipse(leftPad + spacing, topPad + spacing, size, size);
|
||||||
|
g.fillEllipse(leftPad + spacing, topPad + 2 * spacing, size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectsListComponent::resized() {
|
||||||
|
auto area = getLocalBounds();
|
||||||
|
area.removeFromLeft(20);
|
||||||
|
effectComponent->setBounds(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
juce::Component* EffectsListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||||
|
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
||||||
|
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
||||||
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
|
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.01, 0, data.getText(rowNumber), data.getId(rowNumber));
|
||||||
|
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, effectComponent);
|
||||||
|
}
|
||||||
|
return item.release();
|
||||||
|
}
|
|
@ -3,14 +3,15 @@
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
#include "../PluginProcessor.h"
|
#include "../PluginProcessor.h"
|
||||||
#include "../audio/Effect.h"
|
#include "../audio/Effect.h"
|
||||||
|
#include "EffectComponent.h"
|
||||||
|
|
||||||
// Application-specific data container
|
// Application-specific data container
|
||||||
struct MyListBoxItemData : public DraggableListBoxItemData
|
struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Effect>> data;
|
std::vector<std::shared_ptr<Effect>> data;
|
||||||
OscirenderAudioProcessor& audioProcessor;
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
|
||||||
MyListBoxItemData(OscirenderAudioProcessor& p) : audioProcessor(p) {}
|
AudioEffectListBoxItemData(OscirenderAudioProcessor& p) : audioProcessor(p) {}
|
||||||
|
|
||||||
int getNumItems() override {
|
int getNumItems() override {
|
||||||
return data.size();
|
return data.size();
|
||||||
|
@ -24,14 +25,6 @@ struct MyListBoxItemData : public DraggableListBoxItemData
|
||||||
// data.push_back(juce::String("Yahoo"));
|
// data.push_back(juce::String("Yahoo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintContents(int rowNum, juce::Graphics& g, juce::Rectangle<int> bounds) override {
|
|
||||||
g.fillAll(juce::Colours::lightgrey);
|
|
||||||
g.setColour(juce::Colours::black);
|
|
||||||
g.drawRect(bounds);
|
|
||||||
bounds.removeFromLeft(30);
|
|
||||||
g.drawText(data[rowNum]->getName(), bounds, juce::Justification::left);
|
|
||||||
}
|
|
||||||
|
|
||||||
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
|
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
|
||||||
auto effect = data[indexOfItemToMove];
|
auto effect = data[indexOfItemToMove];
|
||||||
|
|
||||||
|
@ -98,32 +91,27 @@ struct MyListBoxItemData : public DraggableListBoxItemData
|
||||||
};
|
};
|
||||||
|
|
||||||
// Custom list-item Component (which includes item-delete button)
|
// Custom list-item Component (which includes item-delete button)
|
||||||
class MyListComponent : public DraggableListBoxItem
|
class EffectsListComponent : public DraggableListBoxItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn);
|
EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<EffectComponent> effectComponent);
|
||||||
~MyListComponent();
|
~EffectsListComponent();
|
||||||
|
|
||||||
void paint(juce::Graphics&) override;
|
void paint(juce::Graphics& g) override;
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
juce::Rectangle<int> dataArea;
|
std::shared_ptr<EffectComponent> effectComponent;
|
||||||
|
|
||||||
juce::Slider slider;
|
|
||||||
juce::String id;
|
|
||||||
juce::ToggleButton selected;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MyListComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Customized DraggableListBoxModel overrides refreshComponentForRow() to ensure that every
|
// Customized DraggableListBoxModel overrides refreshComponentForRow() to ensure that every
|
||||||
// list-item Component is a MyListComponent.
|
// list-item Component is a EffectsListComponent.
|
||||||
class MyListBoxModel : public DraggableListBoxModel
|
class EffectsListBoxModel : public DraggableListBoxModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MyListBoxModel(DraggableListBox& lb, DraggableListBoxItemData& md)
|
EffectsListBoxModel(DraggableListBox& lb, DraggableListBoxItemData& md)
|
||||||
: DraggableListBoxModel(lb, md) {}
|
: DraggableListBoxModel(lb, md) {}
|
||||||
|
|
||||||
juce::Component* refreshComponentForRow(int, bool, juce::Component*) override;
|
juce::Component* refreshComponentForRow(int, bool, juce::Component*) override;
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "LuaListComponent.h"
|
||||||
|
|
||||||
|
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) {
|
||||||
|
effectComponent = std::make_shared<EffectComponent>(0.0, 1.0, 0.01, effect);
|
||||||
|
effectComponent->setHideCheckbox(true);
|
||||||
|
|
||||||
|
effectComponent->slider.onValueChange = [this, &effect, &p] {
|
||||||
|
effect.setValue(effectComponent->slider.getValue());
|
||||||
|
effect.apply(0, Vector2());
|
||||||
|
};
|
||||||
|
|
||||||
|
addAndMakeVisible(*effectComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaListComponent::~LuaListComponent() {}
|
||||||
|
|
||||||
|
void LuaListComponent::resized() {
|
||||||
|
effectComponent->setBounds(getLocalBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
void paintListBoxItem(int sliderNum, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||||
|
|
||||||
|
int LuaListBoxModel::getNumRows() {
|
||||||
|
return audioProcessor.luaEffects.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaListBoxModel::paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||||
|
|
||||||
|
juce::Component* LuaListBoxModel::refreshComponentForRow(int rowNum, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||||
|
if (rowNum < getNumRows() - 1) {
|
||||||
|
std::unique_ptr<LuaListComponent> item(dynamic_cast<LuaListComponent*>(existingComponentToUpdate));
|
||||||
|
if (juce::isPositiveAndBelow(rowNum, getNumRows())) {
|
||||||
|
item = std::make_unique<LuaListComponent>(audioProcessor, *audioProcessor.luaEffects[rowNum]);
|
||||||
|
}
|
||||||
|
return item.release();
|
||||||
|
} else {
|
||||||
|
std::unique_ptr<juce::TextButton> item(dynamic_cast<juce::TextButton*>(existingComponentToUpdate));
|
||||||
|
item = std::make_unique<juce::TextButton>("+");
|
||||||
|
item->onClick = [this]() {
|
||||||
|
audioProcessor.addLuaSlider();
|
||||||
|
listBox.updateContent();
|
||||||
|
};
|
||||||
|
return item.release();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "../PluginProcessor.h"
|
||||||
|
#include "../audio/Effect.h"
|
||||||
|
#include "EffectComponent.h"
|
||||||
|
|
||||||
|
class LuaListComponent : public juce::Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaListComponent(OscirenderAudioProcessor& p, Effect& effect);
|
||||||
|
~LuaListComponent();
|
||||||
|
|
||||||
|
void resized() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<EffectComponent> effectComponent;
|
||||||
|
private:
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LuaListComponent)
|
||||||
|
};
|
||||||
|
|
||||||
|
class LuaListBoxModel : public juce::ListBoxModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaListBoxModel(juce::ListBox& lb, OscirenderAudioProcessor& p) : listBox(lb), audioProcessor(p) {}
|
||||||
|
|
||||||
|
int getNumRows() override;
|
||||||
|
void paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) override;
|
||||||
|
juce::Component* refreshComponentForRow(int sliderNum, bool isRowSelected, juce::Component *existingComponentToUpdate) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int numSliders = 5;
|
||||||
|
juce::ListBox& listBox;
|
||||||
|
OscirenderAudioProcessor& audioProcessor;
|
||||||
|
};
|
|
@ -1,50 +0,0 @@
|
||||||
#include "MyListComponent.h"
|
|
||||||
|
|
||||||
MyListComponent::MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn) : DraggableListBoxItem(lb, data, rn) {
|
|
||||||
addAndMakeVisible(slider);
|
|
||||||
addAndMakeVisible(selected);
|
|
||||||
|
|
||||||
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
|
||||||
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
|
||||||
slider.setRange(0.0, 1.0, 0.01);
|
|
||||||
slider.setValue(data.getValue(rn), juce::dontSendNotification);
|
|
||||||
slider.onValueChange = [this] {
|
|
||||||
((MyListBoxItemData&)modelData).setValue(rowNum, slider.getValue());
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if effect is in audioProcessor enabled effects
|
|
||||||
bool isSelected = false;
|
|
||||||
for (auto effect : *data.audioProcessor.enabledEffects) {
|
|
||||||
if (effect->getId() == data.getId(rn)) {
|
|
||||||
isSelected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selected.setToggleState(isSelected, juce::dontSendNotification);
|
|
||||||
selected.onClick = [this] {
|
|
||||||
((MyListBoxItemData&)modelData).setSelected(rowNum, selected.getToggleState());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
MyListComponent::~MyListComponent() {}
|
|
||||||
|
|
||||||
void MyListComponent::paint (juce::Graphics& g) {
|
|
||||||
modelData.paintContents(rowNum, g, dataArea);
|
|
||||||
DraggableListBoxItem::paint(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyListComponent::resized() {
|
|
||||||
auto sliderLeft = 150;
|
|
||||||
slider.setBounds(sliderLeft, 0, getWidth() - sliderLeft - 10, getHeight());
|
|
||||||
selected.setBounds(2, 0, 25, getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
juce::Component* MyListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
|
||||||
std::unique_ptr<MyListComponent> item(dynamic_cast<MyListComponent*>(existingComponentToUpdate));
|
|
||||||
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems()))
|
|
||||||
{
|
|
||||||
item = std::make_unique<MyListComponent>(listBox, (MyListBoxItemData&)modelData, rowNumber);
|
|
||||||
}
|
|
||||||
return item.release();
|
|
||||||
}
|
|
|
@ -8,45 +8,93 @@ LuaParser::LuaParser(juce::String script) {
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
|
|
||||||
this->script = script;
|
this->script = script;
|
||||||
|
parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaParser::~LuaParser() {
|
LuaParser::~LuaParser() {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Shape>> LuaParser::draw() {
|
void LuaParser::parse() {
|
||||||
std::vector<std::unique_ptr<Shape>> shapes;
|
const int ret = luaL_loadstring(L, script.toUTF8());
|
||||||
|
if (ret != 0) {
|
||||||
|
const char* error = lua_tostring(L, -1);
|
||||||
|
DBG(error);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
functionRef = -1;
|
||||||
|
} else {
|
||||||
|
functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
// only the audio thread runs this fuction
|
||||||
lua_pushnumber(L, step);
|
Vector2 LuaParser::draw() {
|
||||||
lua_setglobal(L, "step");
|
Vector2 sample;
|
||||||
|
|
||||||
const int ret = luaL_dostring(L, script.toUTF8());
|
if (functionRef == -1) {
|
||||||
if (ret != 0) {
|
return sample;
|
||||||
const char* error = lua_tostring(L, -1);
|
}
|
||||||
DBG(error);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
} else if (lua_istable(L, -1)) {
|
|
||||||
// get the first element of the table
|
|
||||||
lua_pushinteger(L, 1);
|
|
||||||
lua_gettable(L, -2);
|
|
||||||
float x = (int)lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
// get the second element of the table
|
lua_pushnumber(L, step);
|
||||||
lua_pushinteger(L, 2);
|
lua_setglobal(L, "step");
|
||||||
lua_gettable(L, -2);
|
|
||||||
float y = (int)lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
shapes.push_back(std::make_unique<Vector2>(x, y));
|
// this CANNOT run at the same time as setVariable
|
||||||
}
|
if (updateVariables) {
|
||||||
|
bool expected = false;
|
||||||
|
if (accessingVariables.compare_exchange_strong(expected, true)) {
|
||||||
|
for (int i = 0; i < variableNames.size(); i++) {
|
||||||
|
lua_pushnumber(L, variables[i]);
|
||||||
|
lua_setglobal(L, variableNames[i].toUTF8());
|
||||||
|
DBG("set " + variableNames[i] + " to " + juce::String(variables[i]));
|
||||||
|
}
|
||||||
|
variableNames.clear();
|
||||||
|
variables.clear();
|
||||||
|
accessingVariables = false;
|
||||||
|
updateVariables = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// pop the table
|
lua_geti(L, LUA_REGISTRYINDEX, functionRef);
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
step++;
|
const int ret = lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
const char* error = lua_tostring(L, -1);
|
||||||
|
DBG(error);
|
||||||
|
functionRef = -1;
|
||||||
|
} else if (lua_istable(L, -1)) {
|
||||||
|
// get the first element of the table
|
||||||
|
lua_pushinteger(L, 1);
|
||||||
|
lua_gettable(L, -2);
|
||||||
|
float x = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
// get the second element of the table
|
||||||
|
lua_pushinteger(L, 2);
|
||||||
|
lua_gettable(L, -2);
|
||||||
|
float y = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
sample = Vector2(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shapes;
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
step++;
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this CANNOT run at the same time as draw()
|
||||||
|
// many threads can run this function
|
||||||
|
bool LuaParser::setVariable(juce::String variableName, double value) {
|
||||||
|
bool expected = false;
|
||||||
|
// this is very unlikely to fail, and if it does, it's not a big deal
|
||||||
|
if (accessingVariables.compare_exchange_strong(expected, true)) {
|
||||||
|
variableNames.push_back(variableName);
|
||||||
|
variables.push_back(value);
|
||||||
|
accessingVariables = false;
|
||||||
|
updateVariables = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,18 @@ public:
|
||||||
LuaParser(juce::String script);
|
LuaParser(juce::String script);
|
||||||
~LuaParser();
|
~LuaParser();
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Shape>> draw();
|
Vector2 draw();
|
||||||
|
bool setVariable(juce::String variableName, double value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void parse();
|
||||||
|
|
||||||
|
int functionRef = -1;
|
||||||
long step = 1;
|
long step = 1;
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
juce::String script;
|
juce::String script;
|
||||||
|
std::atomic<bool> updateVariables = false;
|
||||||
|
std::atomic<bool> accessingVariables = false;
|
||||||
|
std::vector<juce::String> variableNames;
|
||||||
|
std::vector<double> variables;
|
||||||
};
|
};
|
|
@ -23,6 +23,8 @@ void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream
|
||||||
} else if (extension == ".lua") {
|
} else if (extension == ".lua") {
|
||||||
lua = std::make_shared<LuaParser>(stream->readEntireStreamAsString());
|
lua = std::make_shared<LuaParser>(stream->readEntireStreamAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sampleSource = lua != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
||||||
|
@ -30,7 +32,6 @@ std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
||||||
auto tempCamera = camera;
|
auto tempCamera = camera;
|
||||||
auto tempSvg = svg;
|
auto tempSvg = svg;
|
||||||
auto tempText = text;
|
auto tempText = text;
|
||||||
auto tempLua = lua;
|
|
||||||
|
|
||||||
if (tempObject != nullptr && tempCamera != nullptr) {
|
if (tempObject != nullptr && tempCamera != nullptr) {
|
||||||
return tempCamera->draw(*tempObject);
|
return tempCamera->draw(*tempObject);
|
||||||
|
@ -38,14 +39,23 @@ std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
||||||
return tempSvg->draw();
|
return tempSvg->draw();
|
||||||
} else if (tempText != nullptr) {
|
} else if (tempText != nullptr) {
|
||||||
return tempText->draw();
|
return tempText->draw();
|
||||||
} else if (tempLua != nullptr) {
|
|
||||||
return tempLua->draw();
|
|
||||||
}
|
}
|
||||||
auto tempShapes = std::vector<std::unique_ptr<Shape>>();
|
auto tempShapes = std::vector<std::unique_ptr<Shape>>();
|
||||||
tempShapes.push_back(std::make_unique<CircleArc>(0, 0, 0.5, 0.5, std::numbers::pi / 4.0, 2 * std::numbers::pi));
|
tempShapes.push_back(std::make_unique<CircleArc>(0, 0, 0.5, 0.5, std::numbers::pi / 4.0, 2 * std::numbers::pi));
|
||||||
return tempShapes;
|
return tempShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 FileParser::nextSample() {
|
||||||
|
auto tempLua = lua;
|
||||||
|
if (tempLua != nullptr) {
|
||||||
|
return tempLua->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileParser::isSample() {
|
||||||
|
return sampleSource;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileParser::isActive() {
|
bool FileParser::isActive() {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
@ -57,3 +67,23 @@ void FileParser::disable() {
|
||||||
void FileParser::enable() {
|
void FileParser::enable() {
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<WorldObject> FileParser::getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Camera> FileParser::getCamera() {
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SvgParser> FileParser::getSvg() {
|
||||||
|
return svg;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<TextParser> FileParser::getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LuaParser> FileParser::getLua() {
|
||||||
|
return lua;
|
||||||
|
}
|
||||||
|
|
|
@ -14,12 +14,21 @@ public:
|
||||||
|
|
||||||
void parse(juce::String extension, std::unique_ptr<juce::InputStream>) override;
|
void parse(juce::String extension, std::unique_ptr<juce::InputStream>) override;
|
||||||
std::vector<std::unique_ptr<Shape>> nextFrame() override;
|
std::vector<std::unique_ptr<Shape>> nextFrame() override;
|
||||||
|
Vector2 nextSample() override;
|
||||||
|
bool isSample() override;
|
||||||
bool isActive() override;
|
bool isActive() override;
|
||||||
void disable() override;
|
void disable() override;
|
||||||
void enable() override;
|
void enable() override;
|
||||||
|
|
||||||
|
std::shared_ptr<WorldObject> getObject();
|
||||||
|
std::shared_ptr<Camera> getCamera();
|
||||||
|
std::shared_ptr<SvgParser> getSvg();
|
||||||
|
std::shared_ptr<TextParser> getText();
|
||||||
|
std::shared_ptr<LuaParser> getLua();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool active = true;
|
bool active = true;
|
||||||
|
bool sampleSource = false;
|
||||||
|
|
||||||
std::shared_ptr<WorldObject> object;
|
std::shared_ptr<WorldObject> object;
|
||||||
std::shared_ptr<Camera> camera;
|
std::shared_ptr<Camera> camera;
|
||||||
|
|
|
@ -14,5 +14,5 @@ public:
|
||||||
private:
|
private:
|
||||||
FrameConsumer& frameConsumer;
|
FrameConsumer& frameConsumer;
|
||||||
std::shared_ptr<FrameSource> frameSource;
|
std::shared_ptr<FrameSource> frameSource;
|
||||||
int sourceFileIndex = 0;
|
int sourceFileIndex = -1;
|
||||||
};
|
};
|
|
@ -9,6 +9,8 @@ class FrameSource {
|
||||||
public:
|
public:
|
||||||
virtual void parse(juce::String extension, std::unique_ptr<juce::InputStream>) = 0;
|
virtual void parse(juce::String extension, std::unique_ptr<juce::InputStream>) = 0;
|
||||||
virtual std::vector<std::unique_ptr<Shape>> nextFrame() = 0;
|
virtual std::vector<std::unique_ptr<Shape>> nextFrame() = 0;
|
||||||
|
virtual Vector2 nextSample() = 0;
|
||||||
|
virtual bool isSample() = 0;
|
||||||
virtual bool isActive() = 0;
|
virtual bool isActive() = 0;
|
||||||
virtual void disable() = 0;
|
virtual void disable() = 0;
|
||||||
virtual void enable() = 0;
|
virtual void enable() = 0;
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
cppLanguageStandard="20" projectLineFeed=" " headerPath="./include">
|
cppLanguageStandard="20" projectLineFeed=" " headerPath="./include">
|
||||||
<MAINGROUP id="j5Ge2T" name="osci-render">
|
<MAINGROUP id="j5Ge2T" name="osci-render">
|
||||||
<GROUP id="{75439074-E50C-362F-1EDF-8B4BE9011259}" name="Source">
|
<GROUP id="{75439074-E50C-362F-1EDF-8B4BE9011259}" name="Source">
|
||||||
|
<FILE id="X26RjJ" name="LuaComponent.cpp" compile="1" resource="0"
|
||||||
|
file="Source/LuaComponent.cpp"/>
|
||||||
|
<FILE id="g5xRHT" name="LuaComponent.h" compile="0" resource="0" file="Source/LuaComponent.h"/>
|
||||||
<GROUP id="{75F6236A-68A5-85DA-EDAE-23D1621601DB}" name="lua">
|
<GROUP id="{75F6236A-68A5-85DA-EDAE-23D1621601DB}" name="lua">
|
||||||
<FILE id="X5i9iw" name="lapi.c" compile="1" resource="0" file="Source/lua/lapi.c"/>
|
<FILE id="X5i9iw" name="lapi.c" compile="1" resource="0" file="Source/lua/lapi.c"/>
|
||||||
<FILE id="J62WSE" name="lapi.h" compile="0" resource="0" file="Source/lua/lapi.h"/>
|
<FILE id="J62WSE" name="lapi.h" compile="0" resource="0" file="Source/lua/lapi.h"/>
|
||||||
|
@ -81,10 +84,18 @@
|
||||||
file="Source/components/DraggableListBox.cpp"/>
|
file="Source/components/DraggableListBox.cpp"/>
|
||||||
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
||||||
file="Source/components/DraggableListBox.h"/>
|
file="Source/components/DraggableListBox.h"/>
|
||||||
<FILE id="M9ImIg" name="MyListComponent.cpp" compile="1" resource="0"
|
<FILE id="xLAEHK" name="EffectComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/components/MyListComponent.cpp"/>
|
file="Source/components/EffectComponent.cpp"/>
|
||||||
<FILE id="goyxlC" name="MyListComponent.h" compile="0" resource="0"
|
<FILE id="u4UCwb" name="EffectComponent.h" compile="0" resource="0"
|
||||||
file="Source/components/MyListComponent.h"/>
|
file="Source/components/EffectComponent.h"/>
|
||||||
|
<FILE id="JG4NCF" name="EffectsListComponent.cpp" compile="1" resource="0"
|
||||||
|
file="Source/components/EffectsListComponent.cpp"/>
|
||||||
|
<FILE id="dcLchL" name="EffectsListComponent.h" compile="0" resource="0"
|
||||||
|
file="Source/components/EffectsListComponent.h"/>
|
||||||
|
<FILE id="qIxm1z" name="LuaListComponent.cpp" compile="1" resource="0"
|
||||||
|
file="Source/components/LuaListComponent.cpp"/>
|
||||||
|
<FILE id="x0Syav" name="LuaListComponent.h" compile="0" resource="0"
|
||||||
|
file="Source/components/LuaListComponent.h"/>
|
||||||
</GROUP>
|
</GROUP>
|
||||||
<GROUP id="{85A33213-D880-BD92-70D8-1901DA6D23F0}" name="audio">
|
<GROUP id="{85A33213-D880-BD92-70D8-1901DA6D23F0}" name="audio">
|
||||||
<FILE id="NWuowi" name="BitCrushEffect.cpp" compile="1" resource="0"
|
<FILE id="NWuowi" name="BitCrushEffect.cpp" compile="1" resource="0"
|
||||||
|
@ -102,6 +113,8 @@
|
||||||
file="Source/audio/EffectApplication.cpp"/>
|
file="Source/audio/EffectApplication.cpp"/>
|
||||||
<FILE id="MIYJ9y" name="EffectApplication.h" compile="0" resource="0"
|
<FILE id="MIYJ9y" name="EffectApplication.h" compile="0" resource="0"
|
||||||
file="Source/audio/EffectApplication.h"/>
|
file="Source/audio/EffectApplication.h"/>
|
||||||
|
<FILE id="uhyh7T" name="LuaEffect.cpp" compile="1" resource="0" file="Source/audio/LuaEffect.cpp"/>
|
||||||
|
<FILE id="jqDcZq" name="LuaEffect.h" compile="0" resource="0" file="Source/audio/LuaEffect.h"/>
|
||||||
<FILE id="PbbNqz" name="RotateEffect.cpp" compile="1" resource="0"
|
<FILE id="PbbNqz" name="RotateEffect.cpp" compile="1" resource="0"
|
||||||
file="Source/audio/RotateEffect.cpp"/>
|
file="Source/audio/RotateEffect.cpp"/>
|
||||||
<FILE id="tUwNZV" name="RotateEffect.h" compile="0" resource="0" file="Source/audio/RotateEffect.h"/>
|
<FILE id="tUwNZV" name="RotateEffect.h" compile="0" resource="0" file="Source/audio/RotateEffect.h"/>
|
||||||
|
@ -196,10 +209,6 @@
|
||||||
<FILE id="GKBQ8j" name="MainComponent.cpp" compile="1" resource="0"
|
<FILE id="GKBQ8j" name="MainComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/MainComponent.cpp"/>
|
file="Source/MainComponent.cpp"/>
|
||||||
<FILE id="RU8fGr" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/>
|
<FILE id="RU8fGr" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/>
|
||||||
<FILE id="PBCW3H" name="EffectComponentGroup.cpp" compile="1" resource="0"
|
|
||||||
file="Source/EffectComponentGroup.cpp"/>
|
|
||||||
<FILE id="FXKqir" name="EffectComponentGroup.h" compile="0" resource="0"
|
|
||||||
file="Source/EffectComponentGroup.h"/>
|
|
||||||
<FILE id="I44EdJ" name="EffectsComponent.cpp" compile="1" resource="0"
|
<FILE id="I44EdJ" name="EffectsComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/EffectsComponent.cpp"/>
|
file="Source/EffectsComponent.cpp"/>
|
||||||
<FILE id="qxxNX3" name="EffectsComponent.h" compile="0" resource="0"
|
<FILE id="qxxNX3" name="EffectsComponent.h" compile="0" resource="0"
|
||||||
|
|
Ładowanie…
Reference in New Issue