Add ability to save state of project to xml

pull/170/head
James Ball 2023-07-25 12:23:27 +01:00
rodzic e56ec999fe
commit c75a036048
6 zmienionych plików z 79 dodań i 30 usunięć

Wyświetl plik

@ -33,8 +33,8 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
#endif
{
producer.startThread();
juce::SpinLock::ScopedLockType lock(effectsLock);
// locking isn't necessary here because we are in the constructor
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<BitCrushEffect>(),
@ -46,19 +46,19 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<RotateEffect>(),
new EffectParameter("2D Rotate", "rotateSpeed", 0.0, 0.0, 1.0)
new EffectParameter("2D Rotate", "2DRotateSpeed", 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<VectorCancellingEffect>(),
new EffectParameter("Vector Cancel", "vectorCancelling", 0.0, 0.0, 1.0)
new EffectParameter("Vector Cancelling", "vectorCancelling", 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<DistortEffect>(false),
new EffectParameter("X Distort", "horizontalDistort", 0.0, 0.0, 1.0)
new EffectParameter("Distort X", "distortX", 0.0, 0.0, 1.0)
));
toggleableEffects.push_back(std::make_shared<Effect>(
std::make_shared<DistortEffect>(true),
new EffectParameter("Y Distort", "verticalDistort", 0.0, 0.0, 1.0)
new EffectParameter("Distort Y", "distortY", 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) {
@ -77,17 +77,17 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
));
toggleableEffects.push_back(std::make_shared<Effect>(
delayEffect,
std::vector<EffectParameter*>{new EffectParameter("Delay Decay", "delayDecay", 0.0, 0.0, 1.0), new EffectParameter("Delay Length", "delayEchoLength", 0.5, 0.0, 1.0)}
std::vector<EffectParameter*>{new EffectParameter("Delay Decay", "delayDecay", 0.0, 0.0, 1.0), new EffectParameter("Delay Length", "delayLength", 0.5, 0.0, 1.0)}
));
toggleableEffects.push_back(std::make_shared<Effect>(
perspectiveEffect,
std::vector<EffectParameter*>{
new EffectParameter("3D Perspective", "depthScale", 0.0, 0.0, 1.0),
new EffectParameter("3D Depth (z)", "zPos", 0.1, 0.0, 1.0),
new EffectParameter("3D Rotate Speed", "rotateSpeed3D", 0.0, -1.0, 1.0),
new EffectParameter("Rotate X", "rotateX", 1.0, -1.0, 1.0),
new EffectParameter("Rotate Y", "rotateY", 1.0, -1.0, 1.0),
new EffectParameter("Rotate Z", "rotateZ", 0.0, -1.0, 1.0),
new EffectParameter("3D Perspective", "perspectiveStrength", 0.0, 0.0, 1.0),
new EffectParameter("Depth (z)", "perspectiveZPos", 0.1, 0.0, 1.0),
new EffectParameter("Rotate Speed", "perspectiveRotateSpeed", 0.0, -1.0, 1.0),
new EffectParameter("Rotate X", "perspectiveRotateX", 1.0, -1.0, 1.0),
new EffectParameter("Rotate Y", "perspectiveRotateY", 1.0, -1.0, 1.0),
new EffectParameter("Rotate Z", "perspectiveRotateZ", 0.0, -1.0, 1.0),
}
));
toggleableEffects.push_back(traceMax);
@ -112,11 +112,11 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
addLuaSlider();
}
auto effects = toggleableEffects;
effects.insert(effects.end(), permanentEffects.begin(), permanentEffects.end());
effects.insert(effects.end(), luaEffects.begin(), luaEffects.end());
allEffects = toggleableEffects;
allEffects.insert(allEffects.end(), permanentEffects.begin(), permanentEffects.end());
allEffects.insert(allEffects.end(), luaEffects.begin(), luaEffects.end());
for (auto effect : effects) {
for (auto effect : allEffects) {
for (auto effectParameter : effect->parameters) {
auto parameters = effectParameter->getParameters();
for (auto parameter : parameters) {
@ -553,26 +553,41 @@ void OscirenderAudioProcessor::incrementShapeDrawing() {
}
//==============================================================================
bool OscirenderAudioProcessor::hasEditor() const
{
bool OscirenderAudioProcessor::hasEditor() const {
return true; // (change this to false if you choose to not supply an editor)
}
juce::AudioProcessorEditor* OscirenderAudioProcessor::createEditor()
{
juce::AudioProcessorEditor* OscirenderAudioProcessor::createEditor() {
return new OscirenderAudioProcessorEditor (*this);
}
//==============================================================================
void OscirenderAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData) {
juce::SpinLock::ScopedLockType lock1(parsersLock);
juce::SpinLock::ScopedLockType lock2(effectsLock);
std::unique_ptr<juce::XmlElement> xml = std::make_unique<juce::XmlElement>("project");
xml->setAttribute("version", ProjectInfo::versionString);
auto effectsXml = xml->createNewChildElement("effects");
for (auto effect : allEffects) {
effect->save(effectsXml->createNewChildElement("effect"));
}
auto perspectiveFunction = xml->createNewChildElement("perspectiveFunction");
perspectiveFunction->addTextElement(juce::Base64::toBase64(perspectiveEffect->getCode()));
auto filesXml = xml->createNewChildElement("files");
for (int i = 0; i < fileBlocks.size(); i++) {
auto fileXml = filesXml->createNewChildElement("file");
fileXml->setAttribute("name", fileNames[i]);
auto fileString = juce::MemoryInputStream(*fileBlocks[i], false).readEntireStreamAsString();
fileXml->addTextElement(juce::Base64::toBase64(fileString));
}
xml->setAttribute("currentFile", currentFile);
DBG(xml->toString());
copyXmlToBinary(*xml, destData);
}
void OscirenderAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInBytes) {
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
}

Wyświetl plik

@ -104,7 +104,7 @@ public:
camera->setFocalLength(values[0]);
}
return input;
}, new EffectParameter("Focal length", "focalLength", 1.0, 0.0, 2.0)
}, new EffectParameter("Focal length", "objFocalLength", 1.0, 0.0, 2.0)
);
BooleanParameter* fixedRotateX = new BooleanParameter("Object Fixed Rotate X", "objFixedRotateX", false);
@ -214,6 +214,7 @@ private:
double lengthIncrement = 0.0;
bool invalidateFrameBuffer = false;
std::vector<std::shared_ptr<Effect>> allEffects;
std::vector<std::shared_ptr<Effect>> permanentEffects;
std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(

Wyświetl plik

@ -148,3 +148,12 @@ juce::String Effect::getId() {
juce::String Effect::getName() {
return parameters[0]->name;
}
void Effect::save(juce::XmlElement* xml) {
if (enabled != nullptr) {
xml->setAttribute("enabled", enabled->getBoolValue());
}
for (auto parameter : parameters) {
parameter->save(xml->createNewChildElement("parameter"));
}
}

Wyświetl plik

@ -27,6 +27,7 @@ public:
void markEnableable(bool enabled);
juce::String getId();
juce::String getName();
void save(juce::XmlElement* xml);
std::vector<EffectParameter*> parameters;
BooleanParameter* enabled;

Wyświetl plik

@ -96,6 +96,14 @@ public:
return juce::AudioProcessorParameter::genericParameter;
}
void save(juce::XmlElement* xml) {
xml->setAttribute("id", paramID);
xml->setAttribute("value", value.load());
xml->setAttribute("min", min.load());
xml->setAttribute("max", max.load());
xml->setAttribute("step", step.load());
}
private:
// value is not necessarily in the range [min, max] so effect applications may need to clip to a valid range
std::atomic<float> value = 0.0;
@ -259,6 +267,10 @@ public:
return (int)LfoType::Static;
}
}
void save(juce::XmlElement* xml) {
xml->setAttribute("lfo", getText(getValue(), 100));
}
};
class EffectParameter : public FloatParameter {
@ -287,5 +299,15 @@ public:
lfoRate = nullptr;
}
void save(juce::XmlElement* xml) {
FloatParameter::save(xml);
if (lfo != nullptr && lfoRate != nullptr) {
auto lfoXml = xml->createNewChildElement("lfo");
lfo->save(lfoXml);
lfoRate->save(lfoXml);
}
}
EffectParameter(juce::String name, juce::String id, float value, float min, float max, float step = 0.001, bool smoothValueChange = true) : FloatParameter(name, id, value, min, max, step), smoothValueChange(smoothValueChange) {}
};

Wyświetl plik

@ -4,7 +4,8 @@
addUsingNamespaceToJuceHeader="0" displaySplashScreen="0" jucerFormatVersion="1"
pluginCharacteristicsValue="pluginProducesMidiOut,pluginWantsMidiIn"
pluginManufacturer="jameshball" aaxIdentifier="sh.ball.oscirender"
cppLanguageStandard="20" projectLineFeed="&#10;" headerPath="./include">
cppLanguageStandard="20" projectLineFeed="&#10;" headerPath="./include"
version="2.0.0">
<MAINGROUP id="j5Ge2T" name="osci-render">
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
<GROUP id="{C2609827-4F4A-1ADA-8BA1-A40C1D92649C}" name="lua">