CustomKnob Control

#include "PluginProcessor.h"
#include "PluginEditor.h"

MyPluginAudioProcessorEditor::MyPluginAudioProcessorEditor (MyPluginAudioProcessor& p)
    : AudioProcessorEditor (&p), audioProcessor (p)
{
    volumeSlider.setRange(-24.0f, 24.0f, 0.1f);
    volumeSlider.setValue(0.0f);
    volumeSlider.setSliderStyle(juce::Slider::Rotary);
    volumeSlider.setTextBoxStyle(juce::Slider::TextBoxBelow, true, 50, 20);
    volumeSlider.addListener(this);
    addAndMakeVisible(volumeSlider);

    customButton = std::make_unique<juce::DrawableButton>("CustomButton", juce::DrawableButton::ImageFitted);
    juce::Image buttonImage = juce::ImageCache::getFromMemory(BinaryData::small_knob_135frames_png, BinaryData::small_knob_135frames_pngSize);
    juce::DrawableImage drawableImage(buttonImage);
    customButton->setImages(&drawableImage);
    customButton->onClick = [this] { buttonClicked(); };
    addAndMakeVisible(customButton.get());
    
    setSize (200, 200);
}

I’m using a regular slider for the control, and I wanted to clarify if I can apply my asset (asset knob x120 pics) to the slider without using custom classes or modifying the JUCE classes, and somehow replace it? Thanks.

I don’t believe there’s anything in stock JUCE. Gotta write your own class. If you look around you can maybe find some code somewhere that someone else wrote.

It’s not too hard to do on your own though – I found this thread the most helpful. How to use filmstrip images (multi row & multi column)

There are other threads too if you search.

Well, I pretty much expected that I’d have to write my own classe’s, but you have to admit it’s a bit strange when I just want to load my own knobs and expect JUCE to already have class’s for that → since 99.99% of the time, it’s as necessary as certain drinks on a weekend.

For me, creating my own isn’t a problem ->the problem is understanding how to link my code to parameter handling from the GUI. That’s my current dead end. I hooked up a system slider yesterday in five minutes. I know I can dig around the forum, but I’m all for having standard classes in the framework something like that…

Anyway. Thank you so much about link.

You don’t really have to do anything for parameter handling. Just inherit from juce::Slider and override the paint method. All the other juce::Slider code will handle the parameters same as before. That’s how I did it anyway.

1 Like

CustomSlider.h

#pragma once

#include <JuceHeader.h>

class CustomSlider : public juce::Slider
{
public:
    CustomSlider();
    ~CustomSlider() override = default;

    void paint(juce::Graphics& g) override;

private:
    juce::Image knobImage;
};

CustomSlider.cpp

#include "CustomSlider.h"

CustomSlider::CustomSlider()
{
    knobImage = juce::ImageCache::getFromMemory(BinaryData::small_knob_135frames_png, BinaryData::small_knob_135frames_pngSize);
    setSliderStyle(juce::Slider::Rotary);
    setTextBoxStyle(juce::Slider::TextBoxBelow, true, 50, 20);
}

void CustomSlider::paint(juce::Graphics& g)
{
    if (knobImage.isValid())
    {
        auto bounds = getLocalBounds().toFloat();
        int numFrames = 135; // slides count
        int frameHeight = knobImage.getHeight() / numFrames;
        int frameWidth = knobImage.getWidth();

        // Calculating slides count
        int currentFrame = static_cast<int>(juce::jmap<float>(getValue(), getMinimum(), getMaximum(), 0.0f, static_cast<float>(numFrames - 1)));

        // 75% from origin size of asset
        float scaleFactor = 0.75f;
        float scaledWidth = frameWidth * scaleFactor;
        float scaledHeight = frameHeight * scaleFactor;

        // centralization
        float x = (bounds.getWidth() - scaledWidth) / 2;
        float y = (bounds.getHeight() - scaledHeight) / 2;

        // cut slide
        g.drawImage(knobImage,
                    x, y, scaledWidth, scaledHeight, // scaling size after scaleFactor
                    0, currentFrame * frameHeight, frameWidt // origin
                    false); // off interpolation
    }
    else
    {
        juce::Slider::paint(g);
    }
}