kopia lustrzana https://github.com/jameshball/osci-render
150 wiersze
5.2 KiB
C++
150 wiersze
5.2 KiB
C++
#include "SliderVisualiserComponent.h"
|
|
|
|
SliderVisualiserComponent::SliderVisualiserComponent(EffectAudioProcessor& processor)
|
|
: audioProcessor(processor)
|
|
{
|
|
sliderVisualiser.setCropRectangle(juce::Rectangle<float>(0.0f, 0.35f, 1.0f, 0.25f));
|
|
sliderVisualiser.setInterceptsMouseClicks(false, false);
|
|
|
|
// Configure slider to be invisible but functional
|
|
slider.setLookAndFeel(nullptr); // Remove any look and feel
|
|
slider.setColour(juce::Slider::trackColourId, juce::Colours::transparentBlack);
|
|
slider.setColour(juce::Slider::backgroundColourId, juce::Colours::transparentBlack);
|
|
slider.setColour(juce::Slider::thumbColourId, juce::Colours::transparentBlack);
|
|
slider.setColour(juce::Slider::textBoxOutlineColourId, juce::Colours::transparentBlack);
|
|
slider.setColour(juce::Slider::textBoxTextColourId, juce::Colours::transparentBlack);
|
|
slider.setColour(juce::Slider::textBoxBackgroundColourId, juce::Colours::transparentBlack);
|
|
slider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
|
|
slider.setRange(0.0, 1.0, 0.001);
|
|
|
|
// Setup default callback
|
|
slider.onValueChange = [this] { updateVisualiser(); };
|
|
|
|
// Set default label
|
|
setLabel("Param");
|
|
|
|
addAndMakeVisible(sliderVisualiser);
|
|
addAndMakeVisible(slider);
|
|
}
|
|
|
|
SliderVisualiserComponent::~SliderVisualiserComponent()
|
|
{
|
|
}
|
|
|
|
void SliderVisualiserComponent::resized()
|
|
{
|
|
auto bounds = getLocalBounds();
|
|
sliderVisualiser.setBounds(bounds);
|
|
|
|
// Scale down the slider to match the visual representation
|
|
// It should only occupy the portion where the slider visuals appear (not the label area)
|
|
int labelWidth = bounds.getWidth() * labelWidthProportion;
|
|
auto sliderBounds = bounds.withTrimmedLeft(labelWidth - 5);
|
|
slider.setBounds(sliderBounds.withTrimmedRight(10)); // Add some padding on the right
|
|
}
|
|
|
|
void SliderVisualiserComponent::setValue(double newValue)
|
|
{
|
|
slider.setValue(newValue);
|
|
}
|
|
|
|
double SliderVisualiserComponent::getValue() const
|
|
{
|
|
return slider.getValue();
|
|
}
|
|
|
|
void SliderVisualiserComponent::setRange(double newMinimum, double newMaximum, double newInterval)
|
|
{
|
|
slider.setRange(newMinimum, newMaximum, newInterval);
|
|
}
|
|
|
|
void SliderVisualiserComponent::addListener(juce::Slider::Listener* listener)
|
|
{
|
|
slider.addListener(listener);
|
|
}
|
|
|
|
void SliderVisualiserComponent::removeListener(juce::Slider::Listener* listener)
|
|
{
|
|
slider.removeListener(listener);
|
|
}
|
|
|
|
void SliderVisualiserComponent::onValueChange(std::function<void()> callback)
|
|
{
|
|
slider.onValueChange = [this, callback]() {
|
|
updateVisualiser();
|
|
callback();
|
|
};
|
|
}
|
|
|
|
void SliderVisualiserComponent::setLabel(const juce::String& labelText)
|
|
{
|
|
// Only update if the label has changed
|
|
if (label != labelText) {
|
|
label = labelText;
|
|
updateLabelShapes();
|
|
updateVisualiser();
|
|
}
|
|
}
|
|
|
|
void SliderVisualiserComponent::updateLabelShapes()
|
|
{
|
|
// Create text shapes using TextParser
|
|
if (label.isNotEmpty()) {
|
|
TextParser labelParser{label, labelFont};
|
|
labelShapes = labelParser.draw();
|
|
|
|
// Calculate the center of the label area
|
|
double labelCenter = -1.0 + (labelWidthProportion * 1.0); // Center of the label area in oscilloscope space
|
|
|
|
// Scale and position the label shapes to appear on the left side
|
|
for (auto& shape : labelShapes) {
|
|
// Scale down the text to fit nicely
|
|
shape->scale(0.3, 0.3, 1.0);
|
|
// Position centered in the label area
|
|
shape->translate(labelCenter, 0.0, 0.0);
|
|
}
|
|
} else {
|
|
labelShapes.clear();
|
|
}
|
|
}
|
|
|
|
void SliderVisualiserComponent::updateVisualiser()
|
|
{
|
|
// Create shapes for the slider indicator
|
|
std::vector<std::unique_ptr<osci::Shape>> combinedShapes;
|
|
|
|
// First add the label shapes
|
|
for (auto& shape : labelShapes) {
|
|
combinedShapes.push_back(shape->clone());
|
|
}
|
|
|
|
// Calculate the visualizer coordinates that exactly match our component layout
|
|
// Convert component coordinates to oscilloscope coordinates (-1.0 to 1.0)
|
|
double sliderStart = -1.0 + (labelWidthProportion * 2.0); // Scaled from component space to oscilloscope space
|
|
double sliderEnd = 1.0;
|
|
double sliderRange = sliderEnd - sliderStart;
|
|
|
|
double value = slider.getValue();
|
|
double circleRadius = 0.07;
|
|
|
|
// Map the normalized slider value (0-1) to our visual slider range
|
|
double xPos = sliderStart + (value * sliderRange);
|
|
|
|
// Add the left line only if there's space for it (circle not at left edge)
|
|
if (xPos - circleRadius > sliderStart) {
|
|
combinedShapes.push_back(std::make_unique<osci::Line>(sliderStart, 0.0, xPos - circleRadius, 0.0)); // Left line
|
|
}
|
|
|
|
// Add the right line only if there's space for it (circle not at right edge)
|
|
if (xPos + circleRadius < sliderEnd) {
|
|
combinedShapes.push_back(std::make_unique<osci::Line>(xPos + circleRadius, 0.0, sliderEnd, 0.0)); // Right line
|
|
}
|
|
|
|
// Add circle
|
|
combinedShapes.push_back(std::make_unique<osci::CircleArc>(xPos, 0.0, circleRadius, circleRadius, 0.0, 2.0 * M_PI));
|
|
|
|
juce::SpinLock::ScopedLockType lock(audioProcessor.sliderLock);
|
|
// Set the shapes in the renderer
|
|
audioProcessor.sliderRenderer.setShapes(std::move(combinedShapes));
|
|
}
|