Improve the look of the timeline and the volume component, and show error when opening large video files, and fix several bugs

pull/300/head
James H Ball 2025-04-24 17:13:45 +01:00
rodzic 114a7bf66f
commit 0150dcde51
11 zmienionych plików z 236 dodań i 166 usunięć

Wyświetl plik

@ -67,6 +67,10 @@ void FrameSettingsComponent::resized() {
auto firstColumn = area.removeFromLeft(220);
if (juce::JUCEApplicationBase::isStandaloneApp()) {
timeline.setVisible(animated);
}
if (animated) {
if (juce::JUCEApplicationBase::isStandaloneApp()) {
timeline.setBounds(timelineArea);

Wyświetl plik

@ -10,10 +10,10 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
fileButton.setButtonText("Choose File(s)");
fileButton.onClick = [this] {
juce::String fileFormats = "*.obj;*.svg;*.lua;*.txt;*.gpla;*.gif;*.png;*.jpg;*.jpeg;*.wav;*.aiff;*.ogg;*.flac;*.mp3";
#if OSCI_PREMIUM
fileFormats += ";*.mp4;*.mov";
#endif
juce::String fileFormats;
for (auto& ext : audioProcessor.FILE_EXTENSIONS) {
fileFormats += "*." + ext + ";";
}
chooser = std::make_unique<juce::FileChooser>("Open", audioProcessor.getLastOpenedDirectory(), fileFormats);
auto flags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectMultipleItems |
juce::FileBrowserComponent::canSelectFiles;

Wyświetl plik

@ -127,21 +127,10 @@ bool OscirenderAudioProcessorEditor::isInterestedInFileDrag(const juce::StringAr
return false;
}
juce::File file(files[0]);
return
file.hasFileExtension("wav") ||
file.hasFileExtension("aiff") ||
file.hasFileExtension("ogg") ||
file.hasFileExtension("flac") ||
file.hasFileExtension("mp3") ||
file.hasFileExtension("osci") ||
file.hasFileExtension("txt") ||
file.hasFileExtension("lua") ||
file.hasFileExtension("svg") ||
file.hasFileExtension("obj") ||
file.hasFileExtension("gif") ||
file.hasFileExtension("png") ||
file.hasFileExtension("jpg") ||
file.hasFileExtension("gpla");
juce::String ext = file.getFileExtension().toLowerCase();
if (std::find(audioProcessor.FILE_EXTENSIONS.begin(), audioProcessor.FILE_EXTENSIONS.end(), ext) != audioProcessor.FILE_EXTENSIONS.end()) {
return true;
}
}
void OscirenderAudioProcessorEditor::filesDropped(const juce::StringArray& files, int x, int y) {
@ -164,7 +153,18 @@ void OscirenderAudioProcessorEditor::filesDropped(const juce::StringArray& files
bool OscirenderAudioProcessorEditor::isBinaryFile(juce::String name) {
name = name.toLowerCase();
return name.endsWith(".gpla") || name.endsWith(".gif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".wav") || name.endsWith(".aiff") || name.endsWith(".ogg") || name.endsWith(".mp3") || name.endsWith(".flac");
return name.endsWith(".gpla")
|| name.endsWith(".gif")
|| name.endsWith(".png")
|| name.endsWith(".jpg")
|| name.endsWith(".jpeg")
|| name.endsWith(".wav")
|| name.endsWith(".aiff")
|| name.endsWith(".ogg")
|| name.endsWith(".mp3")
|| name.endsWith(".flac")
|| name.endsWith(".mp4")
|| name.endsWith(".mov");
}
// parsersLock must be held

Wyświetl plik

@ -213,6 +213,27 @@ public:
// Added declaration for the new `removeParser` method.
void removeParser(FileParser* parser);
const std::vector<juce::String> FILE_EXTENSIONS = {
"obj",
"svg",
"lua",
"txt",
"gpla",
"gif",
"png",
"jpg",
"jpeg",
"wav",
"aiff",
"ogg",
"flac",
"mp3",
#if OSCI_PREMIUM
"mp4",
"mov",
#endif
};
private:
std::atomic<bool> prevMidiEnabled = !midiEnabled->getBoolValue();

Wyświetl plik

@ -68,8 +68,8 @@ void SosciPluginEditor::resized() {
menuBar.setBounds(area.removeFromTop(25));
if (juce::JUCEApplication::isStandaloneApp()) {
auto volumeArea = area.removeFromLeft(30);
volume.setBounds(volumeArea.withSizeKeepingCentre(volumeArea.getWidth(), juce::jmin(volumeArea.getHeight(), 300)));
auto volumeArea = area.removeFromLeft(35);
volume.setBounds(volumeArea.withSizeKeepingCentre(30, juce::jmin(volumeArea.getHeight(), 300)));
}
auto settingsArea = area.removeFromRight(juce::jmax(juce::jmin(0.4 * getWidth(), 550.0), 350.0));

Wyświetl plik

@ -11,9 +11,6 @@ TimelineComponent::TimelineComponent()
slider.setColour(juce::Slider::ColourIds::trackColourId, juce::Colours::white.withAlpha(0.8f));
slider.setColour(juce::Slider::ColourIds::backgroundColourId, juce::Colours::white.withAlpha(0.2f));
slider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::white);
// Add tooltips
slider.setTooltip("Drag to seek through the timeline");
addChildComponent(playButton);
addChildComponent(pauseButton);
@ -24,7 +21,7 @@ TimelineComponent::TimelineComponent()
playButton.setTooltip("Play");
pauseButton.setTooltip("Pause");
stopButton.setTooltip("Stop");
repeatButton.setTooltip("Toggle repeat mode");
repeatButton.setTooltip("Loop");
slider.setMouseDragSensitivity(150); // Make slider more responsive

Wyświetl plik

@ -50,7 +50,7 @@ public:
g.strokePath(valueTrack, { trackWidth, juce::PathStrokeType::curved, juce::PathStrokeType::rounded });
// Draw thumb
auto thumbWidth = getSliderThumbRadius(slider);
auto thumbWidth = 10;
g.setColour(slider.findColour(juce::Slider::thumbColourId));
// Draw a more modern rectangular thumb with rounded corners

Wyświetl plik

@ -7,6 +7,11 @@ VolumeComponent::VolumeComponent(CommonAudioProcessor& p)
setOpaque(false);
setShouldBeRunning(true);
leftVolumeSmoothed.reset(10); // Reset with 5 steps for smooth animation
rightVolumeSmoothed.reset(10);
leftVolumeSmoothed.setCurrentAndTargetValue(0.0f);
rightVolumeSmoothed.setCurrentAndTargetValue(0.0f);
addAndMakeVisible(volumeSlider);
volumeSlider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical);
volumeSlider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
@ -18,7 +23,7 @@ VolumeComponent::VolumeComponent(CommonAudioProcessor& p)
volumeSlider.setValue(volumeParam->getValueUnnormalised());
volumeSlider.setDoubleClickReturnValue(true, 1.0);
volumeSlider.setLookAndFeel(&thumbRadiusLookAndFeel);
volumeSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::black);
volumeSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::white);
addAndMakeVisible(thresholdSlider);
thresholdSlider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical);
@ -45,45 +50,83 @@ VolumeComponent::VolumeComponent(CommonAudioProcessor& p)
volumeButton.onClick = [this] {
audioProcessor.muteParameter->setBoolValueNotifyingHost(!audioProcessor.muteParameter->getBoolValue());
};
auto doc = juce::XmlDocument::parse(BinaryData::threshold_svg);
thresholdIcon = juce::Drawable::createFromSVG(*doc);
addAndMakeVisible(*thresholdIcon);
}
void VolumeComponent::paint(juce::Graphics& g) {
g.setColour(juce::Colours::transparentBlack);
g.fillAll();
auto r = getLocalBounds().toFloat();
r.removeFromTop(20);
r.removeFromRight(r.getWidth() / 2);
r.removeFromTop(volumeSlider.getLookAndFeel().getSliderThumbRadius(volumeSlider));
r.removeFromBottom(volumeSlider.getLookAndFeel().getSliderThumbRadius(volumeSlider));
g.setColour(juce::Colours::white);
g.fillRect(r);
auto channelHeight = r.getHeight();
auto leftVolumeHeight = channelHeight * leftVolume;
auto rightVolumeHeight = channelHeight * rightVolume;
auto overallRect = r;
auto leftRect = r.removeFromLeft(r.getWidth() / 2);
auto rightRect = r;
auto leftRegion = leftRect;
auto rightRegion = rightRect;
g.setGradientFill(juce::ColourGradient(juce::Colour(0xff00ff00), 0, leftRect.getBottom(), juce::Colours::red, 0, leftRect.getY(), false));
g.fillRect(leftRect.removeFromBottom(leftVolumeHeight));
g.setColour(juce::Colours::white.withAlpha(0.1f));
g.drawRoundedRectangle(overallRect, 4.0f, 1.0f);
g.setGradientFill(juce::ColourGradient(juce::Colour(0xff00ff00), 0, rightRect.getBottom(), juce::Colours::red, 0, rightRect.getY(), false));
g.fillRect(rightRect.removeFromBottom(rightVolumeHeight));
// Enable anti-aliasing for smoother rendering
g.setImageResamplingQuality(juce::Graphics::highResamplingQuality);
auto barWidth = 5.0f;
auto drawVolumeMeter = [&](juce::Rectangle<float>& rect, float volume) {
auto meterRect = rect.removeFromBottom(volume * channelHeight);
auto gradient = juce::ColourGradient(
juce::Colour(0xff00ff00), // Green
0, overallRect.getBottom(),
juce::Colour(0xffff0000), // Red
0, overallRect.getY(),
false);
gradient.addColour(0.3, juce::Colour(0xffffe600)); // Yellow in the middle
g.setGradientFill(gradient);
// Draw rounded meter
g.saveState();
g.reduceClipRegion(meterRect.toNearestInt());
g.fillRoundedRectangle(meterRect.reduced(1.0f), 2.0f);
g.restoreState();
};
g.setColour(juce::Colours::black);
g.fillRect(leftRegion.getX(), leftRegion.getBottom() - (avgLeftVolume * channelHeight) - barWidth / 2, leftRegion.getWidth(), barWidth);
g.fillRect(rightRegion.getX(), rightRegion.getBottom() - (avgRightVolume * channelHeight) - barWidth / 2, rightRegion.getWidth(), barWidth);
drawVolumeMeter(leftRect, leftVolume);
drawVolumeMeter(rightRect, rightVolume);
g.fillRect(leftRegion.getX(), rightRegion.getBottom() - (thresholdSlider.getValue() * channelHeight) - barWidth / 2, leftRegion.getWidth() + rightRegion.getWidth(), barWidth);
// Draw smooth volume indicators
auto drawSmoothIndicator = [&](const juce::Rectangle<float>& region, float value) {
if (value > 0.0f) { // Only draw indicator if volume is greater than 0
auto y = region.getBottom() - (value * channelHeight);
auto indicatorHeight = 3.0f;
auto indicatorRect = juce::Rectangle<float>(
region.getX(), y - indicatorHeight / 2,
region.getWidth(), indicatorHeight);
g.setColour(juce::Colours::white.withAlpha(0.8f));
g.fillRoundedRectangle(indicatorRect, 1.5f);
}
};
drawSmoothIndicator(leftRegion, leftVolumeSmoothed.getNextValue());
drawSmoothIndicator(rightRegion, rightVolumeSmoothed.getNextValue());
// Draw threshold line with modern style
auto thresholdY = rightRegion.getBottom() - (thresholdSlider.getValue() * channelHeight);
auto thresholdRect = juce::Rectangle<float>(
leftRegion.getX(),
thresholdY - 1.5f,
leftRegion.getWidth() + rightRegion.getWidth(),
3.0f
);
g.setColour(juce::Colours::white.withAlpha(0.7f));
g.fillRoundedRectangle(thresholdRect, 1.5f);
}
void VolumeComponent::handleAsyncUpdate() {
@ -108,12 +151,12 @@ void VolumeComponent::runTask(const std::vector<osci::Point>& buffer) {
leftVolume = 0;
rightVolume = 0;
}
this->leftVolume = leftVolume;
this->rightVolume = rightVolume;
avgLeftVolume = (avgLeftVolume * 0.95) + (leftVolume * 0.05);
avgRightVolume = (avgRightVolume * 0.95) + (rightVolume * 0.05);
leftVolumeSmoothed.setTargetValue(leftVolume);
rightVolumeSmoothed.setTargetValue(rightVolume);
triggerAsyncUpdate();
}
@ -128,11 +171,8 @@ void VolumeComponent::resized() {
auto r = getLocalBounds();
auto iconRow = r.removeFromTop(20);
auto volumeRect = iconRow.removeFromLeft(iconRow.getWidth() / 2);
volumeButton.setBounds(volumeRect.expanded(3));
thresholdIcon->setTransformToFit(iconRow.reduced(2).toFloat(), juce::RectanglePlacement::centred);
volumeButton.setBounds(iconRow);
volumeSlider.setBounds(r.removeFromLeft(r.getWidth() / 2));
auto radius = volumeSlider.getLookAndFeel().getSliderThumbRadius(volumeSlider);
thresholdSlider.setBounds(r.reduced(0, radius / 2));
thresholdSlider.setBounds(r.reduced(0, 5.0));
}

Wyświetl plik

@ -26,32 +26,29 @@ public:
float kx = (float) x + (float) width * 0.5f;
float ky = sliderPos;
auto outlineThickness = slider.isEnabled() ? 0.8f : 0.3f;
auto sliderRadius = (float) getSliderThumbRadius(slider);
auto diameter = sliderRadius * 2.0f;
auto halfThickness = outlineThickness * 0.5f;
auto isDownOrDragging = slider.isEnabled() && (slider.isMouseOverOrDragging() || slider.isMouseButtonDown());
auto knobColour = slider.findColour(juce::Slider::thumbColourId)
.withMultipliedSaturation((slider.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
.withMultipliedAlpha(slider.isEnabled() ? 1.0f : 0.7f);
y = (int) (ky - sliderRadius);
// draw triangle that points left
// Create a simple arrow path inspired by the SVG
juce::Path p;
p.addTriangle(
x + diameter, y,
x + diameter, y + diameter,
x, ky
);
float arrowWidth = diameter;
float arrowHeight = diameter;
// Start at the point of the arrow
p.startNewSubPath(x, y + arrowHeight * 0.5f);
// Draw line to top-right corner
p.lineTo(x + arrowWidth, y);
// Draw line to bottom-right corner
p.lineTo(x + arrowWidth, y + arrowHeight);
// Close the path back to the point
p.closeSubPath();
g.setColour(knobColour);
g.setColour(juce::Colours::white.withAlpha(isDownOrDragging ? 1.0f : 0.9f));
g.fillPath(p);
g.setColour(slider.findColour(sliderThumbOutlineColourId));
g.strokePath(p, juce::PathStrokeType(outlineThickness));
}
void drawLinearSlider(juce::Graphics& g, int x, int y, int width, int height, float sliderPos, float minSliderPos, float maxSliderPos, const juce::Slider::SliderStyle style, juce::Slider& slider) override {
@ -74,22 +71,23 @@ private:
CommonAudioProcessor& audioProcessor;
const int DEFAULT_SAMPLE_RATE = 192000;
const double BUFFER_DURATION_SECS = 0.02;
const double BUFFER_DURATION_SECS = 1.0/60.0;
int sampleRate = DEFAULT_SAMPLE_RATE;
std::atomic<float> leftVolume = 0;
std::atomic<float> rightVolume = 0;
std::atomic<float> avgLeftVolume = 0;
std::atomic<float> avgRightVolume = 0;
ThumbRadiusLookAndFeel thumbRadiusLookAndFeel{20};
ThumbRadiusLookAndFeel thumbRadiusLookAndFeel{12};
juce::Slider volumeSlider;
ThresholdLookAndFeel thresholdLookAndFeel{7};
juce::Slider thresholdSlider;
SvgButton volumeButton = SvgButton("VolumeButton", BinaryData::volume_svg, juce::Colours::white, juce::Colours::red, audioProcessor.muteParameter, BinaryData::mute_svg);
std::unique_ptr<juce::Drawable> thresholdIcon;
// Animation smoothing
juce::SmoothedValue<float> leftVolumeSmoothed;
juce::SmoothedValue<float> rightVolumeSmoothed;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VolumeComponent)
};

Wyświetl plik

@ -5,6 +5,47 @@
FileParser::FileParser(OscirenderAudioProcessor &p, std::function<void(int, juce::String, juce::String)> errorCallback)
: errorCallback(errorCallback), audioProcessor(p) {}
// Helper function to show file size warning
void FileParser::showFileSizeWarning(juce::String fileName, int64_t totalBytes, int64_t mbLimit,
juce::String fileType, std::function<void()> callback) {
if (totalBytes <= mbLimit * 1024 * 1024) {
callback();
return;
}
const double fileSizeMB = totalBytes / (1024.0 * 1024.0);
juce::String message = juce::String::formatted(
"The %s file '%s' you're trying to open is %.2f MB in size, and may time a long time to open. "
"Would you like to continue loading it?", fileType.toRawUTF8(), fileName.toRawUTF8(), fileSizeMB);
juce::MessageManager::callAsync([this, message, callback]() {
juce::AlertWindow::showOkCancelBox(
juce::AlertWindow::WarningIcon,
"Large File",
message,
"Continue",
"Cancel",
nullptr,
juce::ModalCallbackFunction::create([this, callback](int result) {
juce::SpinLock::ScopedLockType scope(lock);
if (result == 1) { // 1 = OK button pressed
callback();
} else {
disable(); // Mark this parser as inactive
// Notify the processor to remove this parser
juce::MessageManager::callAsync([this] {
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
audioProcessor.removeParser(this);
});
}
})
);
});
}
void FileParser::parse(juce::String fileId, juce::String fileName, juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font) {
juce::SpinLock::ScopedLockType scope(lock);
@ -21,54 +62,13 @@ void FileParser::parse(juce::String fileId, juce::String fileName, juce::String
wav = nullptr;
if (extension == ".obj") {
// Check file size before parsing
const int64_t fileSize = stream->getTotalLength();
const int64_t oneMB = 1024 * 1024; // 1MB in bytes
// Save the file content to avoid losing it after the async operation
juce::String objContent = stream->readEntireStreamAsString();
if (fileSize > oneMB) {
// For large files, show an async warning dialog
const double fileSizeMB = fileSize / (1024.0 * 1024.0);
juce::MessageManager::callAsync([this, objContent, fileSizeMB, fileName]() {
juce::String message = juce::String::formatted(
"The OBJ file '%s' you're trying to open is %.2f MB in size, which may cause performance issues. "
"Would you like to continue loading it?", fileName.toRawUTF8(), fileSizeMB);
// Show async dialog with callbacks for user response
juce::AlertWindow::showOkCancelBox(
juce::AlertWindow::WarningIcon,
"Large OBJ File",
message,
"Continue",
"Cancel",
nullptr,
juce::ModalCallbackFunction::create([this, objContent](int result) {
if (result == 1) { // 1 = OK button pressed
juce::SpinLock::ScopedLockType scope(lock);
// User chose to continue, load the file
object = std::make_shared<WorldObject>(objContent.toStdString());
} else {
// User canceled, fully close this file parser
juce::SpinLock::ScopedLockType scope(lock);
disable(); // Mark this parser as inactive
// Notify the processor to remove this parser
juce::MessageManager::callAsync([this] {
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
audioProcessor.removeParser(this);
});
}
})
);
});
} else {
// For small files, load immediately
showFileSizeWarning(fileName, fileSize, 1, "OBJ", [this, objContent]() {
object = std::make_shared<WorldObject>(objContent.toStdString());
}
isAnimatable = false;
sampleSource = false;
});
} else if (extension == ".svg") {
svg = std::make_shared<SvgParser>(stream->readEntireStreamAsString());
} else if (extension == ".txt") {
@ -94,16 +94,23 @@ void FileParser::parse(juce::String fileId, juce::String fileName, juce::String
} else if (extension == ".gif" || extension == ".png" || extension == ".jpg" || extension == ".jpeg" || extension == ".mp4" || extension == ".mov") {
juce::MemoryBlock buffer{};
int bytesRead = stream->readIntoMemoryBlock(buffer);
img = std::make_shared<ImageParser>(audioProcessor, extension, buffer);
showFileSizeWarning(fileName, bytesRead, 20, (extension == ".mp4" || extension == ".mov") ? "video" : "image",
[this, buffer, extension]() {
img = std::make_shared<ImageParser>(audioProcessor, extension, buffer);
isAnimatable = extension == ".gif" || extension == ".mp4" || extension == ".mov";
sampleSource = true;
}
);
} else if (extension == ".wav" || extension == ".aiff" || extension == ".flac" || extension == ".ogg" || extension == ".mp3") {
wav = std::make_shared<WavParser>(audioProcessor);
if (!wav->parse(std::move(stream))) {
juce::MessageManager::callAsync([this, fileName] {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon,
"Error Loading " + fileName,
"The audio file '" + fileName + "' could not be loaded.");
});
}
if (!wav->parse(std::move(stream))) {
juce::MessageManager::callAsync([this, fileName] {
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon,
"Error Loading " + fileName,
"The audio file '" + fileName + "' could not be loaded.");
});
}
}
isAnimatable = gpla != nullptr || (img != nullptr && (extension == ".gif" || extension == ".mp4" || extension == ".mov"));
@ -111,83 +118,83 @@ void FileParser::parse(juce::String fileId, juce::String fileName, juce::String
}
std::vector<std::unique_ptr<osci::Shape>> FileParser::nextFrame() {
juce::SpinLock::ScopedLockType scope(lock);
juce::SpinLock::ScopedLockType scope(lock);
if (object != nullptr) {
return object->draw();
} else if (svg != nullptr) {
return svg->draw();
} else if (text != nullptr) {
return text->draw();
} else if (gpla != nullptr) {
return gpla->draw();
}
auto tempShapes = std::vector<std::unique_ptr<osci::Shape>>();
// return a square
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(-0.5, -0.5, 0), osci::Point(0.5, -0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(0.5, -0.5, 0), osci::Point(0.5, 0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(0.5, 0.5, 0), osci::Point(-0.5, 0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(-0.5, 0.5, 0), osci::Point(-0.5, -0.5, 0)));
return tempShapes;
if (object != nullptr) {
return object->draw();
} else if (svg != nullptr) {
return svg->draw();
} else if (text != nullptr) {
return text->draw();
} else if (gpla != nullptr) {
return gpla->draw();
}
auto tempShapes = std::vector<std::unique_ptr<osci::Shape>>();
// return a square
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(-0.5, -0.5, 0), osci::Point(0.5, -0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(0.5, -0.5, 0), osci::Point(0.5, 0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(0.5, 0.5, 0), osci::Point(-0.5, 0.5, 0)));
tempShapes.push_back(std::make_unique<osci::Line>(osci::Point(-0.5, 0.5, 0), osci::Point(-0.5, -0.5, 0)));
return tempShapes;
}
osci::Point FileParser::nextSample(lua_State*& L, LuaVariables& vars) {
juce::SpinLock::ScopedLockType scope(lock);
juce::SpinLock::ScopedLockType scope(lock);
if (lua != nullptr) {
auto values = lua->run(L, vars);
if (values.size() == 2) {
return osci::Point(values[0], values[1], 0);
} else if (values.size() > 2) {
return osci::Point(values[0], values[1], values[2]);
}
} else if (img != nullptr) {
return img->getSample();
} else if (wav != nullptr) {
if (lua != nullptr) {
auto values = lua->run(L, vars);
if (values.size() == 2) {
return osci::Point(values[0], values[1], 0);
} else if (values.size() > 2) {
return osci::Point(values[0], values[1], values[2]);
}
} else if (img != nullptr) {
return img->getSample();
} else if (wav != nullptr) {
return wav->getSample();
}
return osci::Point();
return osci::Point();
}
bool FileParser::isSample() {
return sampleSource;
return sampleSource;
}
bool FileParser::isActive() {
return active;
return active;
}
void FileParser::disable() {
active = false;
active = false;
}
void FileParser::enable() {
active = true;
active = true;
}
std::shared_ptr<WorldObject> FileParser::getObject() {
return object;
return object;
}
std::shared_ptr<SvgParser> FileParser::getSvg() {
return svg;
return svg;
}
std::shared_ptr<TextParser> FileParser::getText() {
return text;
return text;
}
std::shared_ptr<LineArtParser> FileParser::getLineArt() {
return gpla;
return gpla;
}
std::shared_ptr<LuaParser> FileParser::getLua() {
return lua;
return lua;
}
std::shared_ptr<ImageParser> FileParser::getImg() {
return img;
return img;
}
std::shared_ptr<WavParser> FileParser::getWav() {

Wyświetl plik

@ -39,6 +39,9 @@ public:
bool isAnimatable = false;
private:
void showFileSizeWarning(juce::String fileName, int64_t totalBytes, int64_t mbLimit,
juce::String fileType, std::function<void()> callback);
OscirenderAudioProcessor& audioProcessor;
bool active = true;