Hello folks,
I have a really big problem and I ran out of solutions.
I have 8 or 9 images that I am using in my plugin GUI.
They are very small in size. The background image is a jpeg file. It is 500x700 pixels. and 200KB.
Others are png, less than this both in file size and dimensions.
When I try to load only one instance of my plugin, everything works perfectly. With two instances it is still ok. But after 3 or 4 instances it starts lagging the meters and counter of the DAW. After a few more instances, the labels of the plugin start slowing down. The more instances I add, the more lagging occurs.
I was considering using OpenGL but looks like there will be some problems in the future since it is deprecated.
To be honest I don’t know what others are doing but it is obvious that they know something that I don’t know yet
I know that I have a few options.
- filmstrips for all different angles of knobs.
- using only one image and rotating it with drawImageTransformed.
- Image+ generic graphics methods of the juce
- …
Which one of these methods would work faster?
Currently, I use two images. One is a plain pic of the knob without the shadow. The other is the shadow(a transparent png file).
I keep the shadow fixed and I just rotate the knob image. I am using the same logic for all of my knobs.
I tried to use the XCode profile option to see the CPU consumption and it appears that It is because of the drawImage method calls.
Here is the code of my knobs. I am just customizing the slider’s look and feel.
Could you please have a look at the code to see if there is anything wrong?
Do you have any suggestions?
BlackKnob.h file
#include <JuceHeader.h>
//=================================================
class BlackKnob : public juce::Component,
public juce::LookAndFeel_V4,
public juce::Label::Listener
{
public:
BlackKnob();
~BlackKnob() override;
void paint (juce::Graphics&) override;
void resized() override;
void drawRotarySlider(Graphics& g, int x, int y, int width,
int height, float sliderPos,
float rotaryStartAngle, float rotaryEndAngle,
Slider& slider) override;
void triggerClick();
private:
juce::Slider::SliderLayout getSliderLayout (Slider&) override;
Label* createSliderTextBox (Slider& slider) override;
Label *l;
/** Called when a Label's text has changed. */
void labelTextChanged (Label* labelThatHasChanged) override;
//these will define the size of the knob.
float widthOfSlider=60;
float heightOfSlider=80;
double firstClickTime;
int turn = 0;
int isClicked = 0;
long ShowLabelBaseTime=0;
Font arial{"Arial",15,Font::plain};
Image knobImage,knobShadow;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BlackKnob)
};
BlackKnob.cpp
#include <JuceHeader.h>
#include "BlackKnob.h"
//==============================================
BlackKnob::BlackKnob()
{
knobImage = ImageCache::getFromMemory(BinaryData::blackKnob_png,
BinaryData::blackKnob_pngSize);
knobShadow = ImageCache::getFromMemory(BinaryData::shadow_png,
BinaryData::shadow_pngSize);
}
BlackKnob::~BlackKnob()
{
}
void BlackKnob::paint (juce::Graphics& g)
{
}
void BlackKnob::resized()
{
}
void BlackKnob::drawRotarySlider(Graphics& g, int x, int y, int width,
int height, float sliderPos,
float rotaryStartAngle, float rotaryEndAngle,
Slider& slider)
{
// the size of the images are little bit larger than the knobs.
knobImage= knobImage.rescaled(width, width);
knobImage.duplicateIfShared();
knobShadow = knobShadow.rescaled(knobImage.getWidth(), knobImage.getHeight());
knobShadow.duplicateIfShared();
slider.setTextBoxStyle(juce::Slider::TextBoxBelow, false, width, height*0.4f);
Rectangle <float> knobArea(x, y, width, width);
float halfOfDiameter = jmin((float)width,(float)height);
halfOfDiameter=halfOfDiameter/2.0f;
float angle = rotaryStartAngle + (sliderPos * (rotaryEndAngle - rotaryStartAngle)) +2.2;
// I am trying to draw the image at the top of the knob area.
// The label will be at the buttom.
//It works fine for me.
g.setOrigin(0, -height*0.1f);
g.drawImageTransformed(knobImage,
AffineTransform::rotation(angle, halfOfDiameter, halfOfDiameter));
g.drawImage(knobShadow, knobArea);
g.setOrigin(0, +height*0.1f);
// this section just checks some mouse events and label events to display
// the label for a short period of time.
if (((Time::getMillisecondCounter() - firstClickTime) > 500) &&
!(slider.isMouseOverOrDragging() || l->isMouseOverOrDragging()) &&
!(slider.isMouseButtonDownAnywhere() || l->isMouseButtonDownAnywhere()) &&
turn == 1 &&
!l->isBeingEdited())
{
turn = 0;
isClicked = 0;
firstClickTime = Time::getMillisecondCounter();
}
if ((slider.isMouseOverOrDragging() ||
l->isMouseOverOrDragging()) &&
turn==0)
{
isClicked = 1;
firstClickTime = Time::getMillisecondCounter();
turn = 1;
}
if(isClicked==1)
{ ShowLabelBaseTime=Time::getMillisecondCounter(); }
if(Time::getMillisecondCounter()-ShowLabelBaseTime>800 &&isClicked==0)
{ l->setVisible(false); }
else
{ l->setVisible(true); }
slider.setVelocityModeParameters(0.01, 0,0.1, true);// velocity mode has modified
}
void BlackKnob::triggerClick()
{
isClicked=1;
firstClickTime = Time::getMillisecondCounter();
turn = 1;
}
Slider::SliderLayout BlackKnob::getSliderLayout (Slider&)
{
Slider::SliderLayout layout;
layout.sliderBounds = Rectangle<int> (0, 0, widthOfSlider, heightOfSlider);
layout.textBoxBounds = Rectangle<int> (0, heightOfSlider*0.7f, widthOfSlider, heightOfSlider*0.3f);
return layout;
}
void BlackKnob::labelTextChanged (Label* labelThatHasChanged)
{
DBG("changed");
}
Label* BlackKnob::createSliderTextBox (Slider& slider)
{
l = LookAndFeel_V3::createSliderTextBox (slider);
l->setColour(Label::backgroundColourId, Colours::black);
l->setColour (Label::textColourId, Colours::white.withAlpha (1.0f));
l->setFont(arial);
l->addListener(this);
return l;
}