kopia lustrzana https://github.com/jameshball/osci-render
Save size and layout of application and adjust afterglow effect
rodzic
7aa3ed203b
commit
e00f57aaac
|
@ -2,7 +2,7 @@
|
|||
#include "CommonPluginEditor.h"
|
||||
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
|
||||
|
||||
CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String appName, juce::String projectFileType, int width, int height)
|
||||
CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String appName, juce::String projectFileType, int defaultWidth, int defaultHeight)
|
||||
: AudioProcessorEditor(&p), audioProcessor(p), appName(appName), projectFileType(projectFileType)
|
||||
{
|
||||
if (!applicationFolder.exists()) {
|
||||
|
@ -37,6 +37,9 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app
|
|||
}
|
||||
|
||||
addAndMakeVisible(visualiser);
|
||||
|
||||
int width = std::any_cast<int>(audioProcessor.getProperty("appWidth", defaultWidth));
|
||||
int height = std::any_cast<int>(audioProcessor.getProperty("appHeight", defaultHeight));
|
||||
|
||||
visualiserSettings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiserSettings.setSize(550, VISUALISER_SETTINGS_HEIGHT);
|
||||
|
@ -65,6 +68,11 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app
|
|||
#endif
|
||||
}
|
||||
|
||||
void CommonPluginEditor::resized() {
|
||||
audioProcessor.setProperty("appWidth", getWidth());
|
||||
audioProcessor.setProperty("appHeight", getHeight());
|
||||
}
|
||||
|
||||
void CommonPluginEditor::initialiseMenuBar(juce::MenuBarModel& menuBarModel) {
|
||||
menuBar.setModel(&menuBarModel);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
void openAudioSettings();
|
||||
void openRecordingSettings();
|
||||
void resetToDefault();
|
||||
void resized() override;
|
||||
|
||||
private:
|
||||
CommonAudioProcessor& audioProcessor;
|
||||
|
|
|
@ -225,3 +225,79 @@ void CommonAudioProcessor::removeAudioPlayerListener(AudioPlayerListener* listen
|
|||
juce::SpinLock::ScopedLockType lock(audioPlayerListenersLock);
|
||||
audioPlayerListeners.erase(std::remove(audioPlayerListeners.begin(), audioPlayerListeners.end(), listener), audioPlayerListeners.end());
|
||||
}
|
||||
|
||||
std::any CommonAudioProcessor::getProperty(const std::string& key) {
|
||||
juce::SpinLock::ScopedLockType lock(propertiesLock);
|
||||
return properties[key];
|
||||
}
|
||||
|
||||
std::any CommonAudioProcessor::getProperty(const std::string& key, std::any defaultValue) {
|
||||
juce::SpinLock::ScopedLockType lock(propertiesLock);
|
||||
auto it = properties.find(key);
|
||||
if (it == properties.end()) {
|
||||
properties[key] = defaultValue;
|
||||
return defaultValue;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void CommonAudioProcessor::setProperty(const std::string& key, std::any value) {
|
||||
juce::SpinLock::ScopedLockType lock(propertiesLock);
|
||||
properties[key] = value;
|
||||
}
|
||||
|
||||
void CommonAudioProcessor::saveProperties(juce::XmlElement& xml) {
|
||||
juce::SpinLock::ScopedLockType lock(propertiesLock);
|
||||
|
||||
auto propertiesXml = xml.createNewChildElement("properties");
|
||||
|
||||
for (auto& property : properties) {
|
||||
auto element = propertiesXml->createNewChildElement("property");
|
||||
element->setAttribute("key", property.first);
|
||||
if (std::any_cast<int>(&property.second) != nullptr) {
|
||||
element->setAttribute("type", "int");
|
||||
element->setAttribute("value", std::any_cast<int>(property.second));
|
||||
} else if (std::any_cast<float>(&property.second) != nullptr) {
|
||||
element->setAttribute("type", "float");
|
||||
element->setAttribute("value", std::any_cast<float>(property.second));
|
||||
} else if (std::any_cast<double>(&property.second) != nullptr) {
|
||||
element->setAttribute("type", "double");
|
||||
element->setAttribute("value", std::any_cast<double>(property.second));
|
||||
} else if (std::any_cast<bool>(&property.second) != nullptr) {
|
||||
element->setAttribute("type", "bool");
|
||||
element->setAttribute("value", std::any_cast<bool>(property.second));
|
||||
} else if (std::any_cast<juce::String>(&property.second) != nullptr) {
|
||||
element->setAttribute("type", "string");
|
||||
element->setAttribute("value", std::any_cast<juce::String>(property.second));
|
||||
} else {
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommonAudioProcessor::loadProperties(juce::XmlElement& xml) {
|
||||
juce::SpinLock::ScopedLockType lock(propertiesLock);
|
||||
|
||||
auto propertiesXml = xml.getChildByName("properties");
|
||||
|
||||
if (propertiesXml != nullptr) {
|
||||
for (auto property : propertiesXml->getChildIterator()) {
|
||||
auto key = property->getStringAttribute("key").toStdString();
|
||||
auto type = property->getStringAttribute("type");
|
||||
|
||||
if (type == "int") {
|
||||
properties[key] = property->getIntAttribute("value");
|
||||
} else if (type == "float") {
|
||||
properties[key] = property->getDoubleAttribute("value");
|
||||
} else if (type == "double") {
|
||||
properties[key] = property->getDoubleAttribute("value");
|
||||
} else if (type == "bool") {
|
||||
properties[key] = property->getBoolAttribute("value");
|
||||
} else if (type == "string") {
|
||||
properties[key] = property->getStringAttribute("value");
|
||||
} else {
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include <any>
|
||||
#include "concurrency/AudioBackgroundThread.h"
|
||||
#include "concurrency/AudioBackgroundThreadManager.h"
|
||||
#include "audio/SampleRateManager.h"
|
||||
|
@ -59,6 +60,9 @@ public:
|
|||
void stopAudioFile();
|
||||
void addAudioPlayerListener(AudioPlayerListener* listener);
|
||||
void removeAudioPlayerListener(AudioPlayerListener* listener);
|
||||
std::any getProperty(const std::string& key);
|
||||
std::any getProperty(const std::string& key, std::any defaultValue);
|
||||
void setProperty(const std::string& key, std::any value);
|
||||
|
||||
juce::SpinLock audioPlayerListenersLock;
|
||||
std::vector<AudioPlayerListener*> audioPlayerListeners;
|
||||
|
@ -122,6 +126,12 @@ protected:
|
|||
BooleanParameter* getBooleanParameter(juce::String id);
|
||||
FloatParameter* getFloatParameter(juce::String id);
|
||||
IntParameter* getIntParameter(juce::String id);
|
||||
|
||||
void saveProperties(juce::XmlElement& xml);
|
||||
void loadProperties(juce::XmlElement& xml);
|
||||
|
||||
juce::SpinLock propertiesLock;
|
||||
std::unordered_map<std::string, std::any> properties;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CommonAudioProcessor)
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#include "PluginEditor.h"
|
||||
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
|
||||
|
||||
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p)
|
||||
: CommonPluginEditor(p, "osci-render", "osci", 1100, 750), audioProcessor(p), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white) {
|
||||
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p) : CommonPluginEditor(p, "osci-render", "osci", 1100, 750), audioProcessor(p), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white) {
|
||||
#if !SOSCI_FEATURES
|
||||
addAndMakeVisible(upgradeButton);
|
||||
upgradeButton.onClick = [this] {
|
||||
|
@ -28,16 +27,9 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
|
||||
addAndMakeVisible(collapseButton);
|
||||
collapseButton.onClick = [this] {
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
||||
int originalIndex = audioProcessor.getCurrentFileIndex();
|
||||
int index = editingCustomFunction ? 0 : audioProcessor.getCurrentFileIndex() + 1;
|
||||
if (originalIndex != -1 || editingCustomFunction) {
|
||||
codeEditors[index]->setVisible(!codeEditors[index]->isVisible());
|
||||
updateCodeEditor(!editingCustomFunction && isBinaryFile(audioProcessor.getCurrentFileName()));
|
||||
}
|
||||
}
|
||||
setCodeEditorVisible(std::nullopt);
|
||||
};
|
||||
|
||||
juce::Path path;
|
||||
path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f);
|
||||
collapseButton.setShape(path, false, true, true);
|
||||
|
@ -55,17 +47,20 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
audioProcessor.fileChangeBroadcaster.addChangeListener(this);
|
||||
audioProcessor.broadcaster.addChangeListener(this);
|
||||
}
|
||||
|
||||
double codeEditorLayoutPreferredSize = std::any_cast<double>(audioProcessor.getProperty("codeEditorLayoutPreferredSize", -0.7));
|
||||
double luaLayoutPreferredSize = std::any_cast<double>(audioProcessor.getProperty("luaLayoutPreferredSize", -0.7));
|
||||
|
||||
layout.setItemLayout(0, -0.3, -1.0, -0.7);
|
||||
layout.setItemLayout(0, -0.3, -1.0, codeEditorLayoutPreferredSize);
|
||||
layout.setItemLayout(1, RESIZER_BAR_SIZE, RESIZER_BAR_SIZE, RESIZER_BAR_SIZE);
|
||||
layout.setItemLayout(2, -0.0, -1.0, -0.3);
|
||||
layout.setItemLayout(2, -0.0, -1.0, -(1.0 + codeEditorLayoutPreferredSize));
|
||||
|
||||
addAndMakeVisible(settings);
|
||||
addAndMakeVisible(resizerBar);
|
||||
|
||||
luaLayout.setItemLayout(0, -0.3, -1.0, -0.7);
|
||||
luaLayout.setItemLayout(0, -0.3, -1.0, luaLayoutPreferredSize);
|
||||
luaLayout.setItemLayout(1, RESIZER_BAR_SIZE, RESIZER_BAR_SIZE, RESIZER_BAR_SIZE);
|
||||
luaLayout.setItemLayout(2, -0.1, -1.0, -0.3);
|
||||
luaLayout.setItemLayout(2, -0.1, -1.0, -(1.0 + luaLayoutPreferredSize));
|
||||
|
||||
addAndMakeVisible(lua);
|
||||
addAndMakeVisible(luaResizerBar);
|
||||
|
@ -96,6 +91,16 @@ OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {
|
|||
audioProcessor.fileChangeBroadcaster.removeChangeListener(this);
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessorEditor::setCodeEditorVisible(std::optional<bool> visible) {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
|
||||
int originalIndex = audioProcessor.getCurrentFileIndex();
|
||||
int index = editingCustomFunction ? 0 : audioProcessor.getCurrentFileIndex() + 1;
|
||||
if (originalIndex != -1 || editingCustomFunction) {
|
||||
codeEditors[index]->setVisible(visible.has_value() ? visible.value() : !codeEditors[index]->isVisible());
|
||||
updateCodeEditor(!editingCustomFunction && isBinaryFile(audioProcessor.getCurrentFileName()));
|
||||
}
|
||||
}
|
||||
|
||||
bool OscirenderAudioProcessorEditor::isInterestedInFileDrag(const juce::StringArray& files) {
|
||||
if (files.size() != 1) {
|
||||
return false;
|
||||
|
@ -146,7 +151,8 @@ void OscirenderAudioProcessorEditor::initialiseCodeEditors() {
|
|||
for (int i = 0; i < audioProcessor.numFiles(); i++) {
|
||||
addCodeEditor(i);
|
||||
}
|
||||
fileUpdated(audioProcessor.getCurrentFileName());
|
||||
bool codeEditorVisible = std::any_cast<bool>(audioProcessor.getProperty("codeEditorVisible", false));
|
||||
fileUpdated(audioProcessor.getCurrentFileName(), codeEditorVisible);
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessorEditor::paint(juce::Graphics& g) {
|
||||
|
@ -154,6 +160,8 @@ void OscirenderAudioProcessorEditor::paint(juce::Graphics& g) {
|
|||
}
|
||||
|
||||
void OscirenderAudioProcessorEditor::resized() {
|
||||
CommonPluginEditor::resized();
|
||||
|
||||
auto area = getLocalBounds();
|
||||
|
||||
if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) {
|
||||
|
@ -254,6 +262,10 @@ void OscirenderAudioProcessorEditor::resized() {
|
|||
}
|
||||
|
||||
settings.setBounds(area);
|
||||
|
||||
audioProcessor.setProperty("codeEditorLayoutPreferredSize", layout.getItemCurrentRelativeSize(0));
|
||||
audioProcessor.setProperty("luaLayoutPreferredSize", luaLayout.getItemCurrentRelativeSize(0));
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
@ -335,6 +347,9 @@ void OscirenderAudioProcessorEditor::updateCodeEditor(bool binaryFile, bool shou
|
|||
updatingDocumentsWithParserLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
audioProcessor.setProperty("codeEditorVisible", visible);
|
||||
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
|
@ -371,7 +386,7 @@ void OscirenderAudioProcessorEditor::toggleLayout(juce::StretchableLayoutManager
|
|||
layout.getItemLayout(2, minSize, maxSize, preferredSize);
|
||||
layout.getItemLayout(0, otherMinSize, otherMaxSize, otherPreferredSize);
|
||||
|
||||
if (preferredSize == CLOSED_PREF_SIZE) {
|
||||
if (layout.getItemCurrentAbsoluteSize(2) <= CLOSED_PREF_SIZE) {
|
||||
double otherPrefSize = -(1 + prefSize);
|
||||
if (prefSize > 0) {
|
||||
otherPrefSize = -1.0;
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
void codeDocumentTextDeleted(int startIndex, int endIndex) override;
|
||||
void updateCodeDocument();
|
||||
void updateCodeEditor(bool binaryFile, bool shouldOpenEditor = false);
|
||||
void setCodeEditorVisible(std::optional<bool> visible);
|
||||
|
||||
bool keyPressed(const juce::KeyPress& key) override;
|
||||
void mouseDown(const juce::MouseEvent& event) override;
|
||||
|
|
|
@ -665,6 +665,8 @@ void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
|||
xml->setAttribute("currentFile", currentFile);
|
||||
|
||||
recordingParameters.save(xml.get());
|
||||
|
||||
saveProperties(*xml);
|
||||
|
||||
copyXmlToBinary(*xml, destData);
|
||||
}
|
||||
|
@ -780,6 +782,8 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
|
|||
changeCurrentFile(xml->getIntAttribute("currentFile", -1));
|
||||
|
||||
recordingParameters.load(xml.get());
|
||||
|
||||
loadProperties(*xml);
|
||||
|
||||
broadcaster.sendChangeMessage();
|
||||
prevMidiEnabled = !midiEnabled->getBoolValue();
|
||||
|
|
|
@ -10,14 +10,17 @@ SettingsComponent::SettingsComponent(OscirenderAudioProcessor& p, OscirenderAudi
|
|||
addAndMakeVisible(midi);
|
||||
addChildComponent(txt);
|
||||
addChildComponent(frame);
|
||||
|
||||
double midiLayoutPreferredSize = std::any_cast<double>(audioProcessor.getProperty("midiLayoutPreferredSize", pluginEditor.CLOSED_PREF_SIZE));
|
||||
double mainLayoutPreferredSize = std::any_cast<double>(audioProcessor.getProperty("mainLayoutPreferredSize", -0.4));
|
||||
|
||||
midiLayout.setItemLayout(0, -0.1, -1.0, -1.0);
|
||||
midiLayout.setItemLayout(0, -0.1, -1.0, -(1.0 + midiLayoutPreferredSize));
|
||||
midiLayout.setItemLayout(1, pluginEditor.RESIZER_BAR_SIZE, pluginEditor.RESIZER_BAR_SIZE, pluginEditor.RESIZER_BAR_SIZE);
|
||||
midiLayout.setItemLayout(2, pluginEditor.CLOSED_PREF_SIZE, -0.9, pluginEditor.CLOSED_PREF_SIZE);
|
||||
|
||||
mainLayout.setItemLayout(0, -0.1, -0.9, -0.4);
|
||||
midiLayout.setItemLayout(2, pluginEditor.CLOSED_PREF_SIZE, -0.9, midiLayoutPreferredSize);
|
||||
|
||||
mainLayout.setItemLayout(0, -0.1, -0.9, mainLayoutPreferredSize);
|
||||
mainLayout.setItemLayout(1, pluginEditor.RESIZER_BAR_SIZE, pluginEditor.RESIZER_BAR_SIZE, pluginEditor.RESIZER_BAR_SIZE);
|
||||
mainLayout.setItemLayout(2, -0.1, -0.9, -0.6);
|
||||
mainLayout.setItemLayout(2, -0.1, -0.9, -(1.0 + mainLayoutPreferredSize));
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,6 +62,9 @@ void SettingsComponent::resized() {
|
|||
}
|
||||
|
||||
effects.setBounds(dummyBounds);
|
||||
|
||||
audioProcessor.setProperty("midiLayoutPreferredSize", midiLayout.getItemCurrentRelativeSize(2));
|
||||
audioProcessor.setProperty("mainLayoutPreferredSize", mainLayout.getItemCurrentRelativeSize(0));
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
|
|||
}
|
||||
|
||||
void SosciPluginEditor::resized() {
|
||||
CommonPluginEditor::resized();
|
||||
auto area = getLocalBounds();
|
||||
|
||||
if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) {
|
||||
|
|
|
@ -122,6 +122,8 @@ void SosciAudioProcessor::getStateInformation(juce::MemoryBlock& destData) {
|
|||
}
|
||||
|
||||
recordingParameters.save(xml.get());
|
||||
|
||||
saveProperties(*xml);
|
||||
|
||||
copyXmlToBinary(*xml, destData);
|
||||
}
|
||||
|
@ -182,6 +184,8 @@ void SosciAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
|||
}
|
||||
|
||||
recordingParameters.load(xml.get());
|
||||
|
||||
loadProperties(*xml);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@ float hypTan(float x) {
|
|||
|
||||
void main() {
|
||||
vec4 line = texture2D(uTexture0, vTexCoord);
|
||||
float fade = fadeAmount * hypTan(min(line.r / afterglowAmount, 10.0));
|
||||
float x = min(line.r / afterglowAmount, 10.0);
|
||||
float minFade = 0.1 * (1.0 - clamp(afterglowAmount / 10.0, 0.0, 1.0));
|
||||
float fade = fadeAmount * ((1.0 - minFade) * hypTan(x) + minFade);
|
||||
fade = clamp(fade, 0.0, fadeAmount);
|
||||
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, fade);
|
||||
|
|
|
@ -1176,17 +1176,11 @@ void VisualiserComponent::drawCRT() {
|
|||
#if SOSCI_FEATURES
|
||||
outputShader->setUniform("uScreenSaturation", (float) settings.getScreenSaturation());
|
||||
outputShader->setUniform("uHueShift", (float) settings.getScreenHue() / 360.0f);
|
||||
<<<<<<< Updated upstream
|
||||
#else
|
||||
outputShader->setUniform("uScreenSaturation", 1.0f);
|
||||
outputShader->setUniform("uHueShift", 0.0f);
|
||||
=======
|
||||
outputShader->setUniform("uOverexposure", (float) settings.getOverexposure());
|
||||
#else
|
||||
outputShader->setUniform("uScreenSaturation", 1.0f);
|
||||
outputShader->setUniform("uHueShift", 0.0f);
|
||||
outputShader->setUniform("uOverexposure", 0.5f);
|
||||
>>>>>>> Stashed changes
|
||||
#endif
|
||||
outputShader->setUniform("uNoise", (float) settings.getNoise());
|
||||
outputShader->setUniform("uRandom", juce::Random::getSystemRandom().nextFloat());
|
||||
|
|
|
@ -119,9 +119,7 @@ public:
|
|||
"Afterglow",
|
||||
"Controls how quickly the image disappears after glowing brightly. Closely related to persistence.",
|
||||
"afterglow",
|
||||
VERSION_HINT, 1.5, 0.0, 5.0
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
VERSION_HINT, 1.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> overexposureEffect = std::make_shared<Effect>(
|
||||
|
@ -130,7 +128,6 @@ public:
|
|||
"Controls at which point the line becomes overexposed and clips, turning white.",
|
||||
"overexposure",
|
||||
VERSION_HINT, 0.5, 0.0, 1.0
|
||||
>>>>>>> Stashed changes
|
||||
)
|
||||
);
|
||||
std::shared_ptr<StereoEffect> stereoEffectApplication = std::make_shared<StereoEffect>();
|
||||
|
@ -286,10 +283,7 @@ public:
|
|||
afterglowEffect,
|
||||
screenSaturationEffect,
|
||||
screenHueEffect,
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
overexposureEffect,
|
||||
>>>>>>> Stashed changes
|
||||
#endif
|
||||
};
|
||||
std::vector<std::shared_ptr<Effect>> audioEffects = {
|
||||
|
@ -464,10 +458,7 @@ private:
|
|||
std::make_shared<EffectComponent>(*parameters.glowEffect),
|
||||
#if SOSCI_FEATURES
|
||||
std::make_shared<EffectComponent>(*parameters.afterglowEffect),
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
std::make_shared<EffectComponent>(*parameters.overexposureEffect),
|
||||
>>>>>>> Stashed changes
|
||||
#else
|
||||
std::make_shared<EffectComponent>(*parameters.ambientEffect),
|
||||
#endif
|
||||
|
|
Ładowanie…
Reference in New Issue