I’d like to customize the Slider by loading the graphics for its background and the “hold” (the foreground, which the user clicks and drags). Which is the recommended way to do this? Should I inherit the Slider class and then implement the Paint method. However, as far as I can see I only get a single Graphics object reference to the Paint method. Does that reference point at the background or at the Slider “hold”?
Is there a class for a Knob? I have animated stacked frames for knobs, which I used with the VSTGUI and now I’m looking for an easy way to create an animated knob in Juce using these graphics.
Ok. So I use the LookAndFeel class and use drawLinearSliderBackground and drawLinearSliderThumb to draw the background + thumb of the slider.
To load from disk, I use the ImageFileFormat class. Then I create an Image object using ImageFileFormat. Then I create a Graphics object using the Image object. Then I set the Graphics object which is passed to drawLinearSliderThumb. Is that correct?
Is there any support for stacked image frames? Or do I have to split them into individual images and then assign each one depending on which value the slider has?
I dont understand why people do this film strips of images (this reminds me of my very short adventure with VST GUI), you can easily rotate an image, this is more accurate i think:
void NDSLookAndFeel::drawRotarySlider (Graphics &g, int x, int y, int width, int height, float sliderPosProportional, const float rotaryStartAngle, const float rotaryEndAngle, Slider &slider)
{
AffineTransform rotator;
if (!slider.isMouseOverOrDragging())
{
g.drawImage (knobNormal, x,y,width,height,0,0,width,height,false);
}
else
{
g.drawImage (knobOver, x,y,width,height,0,0,width,height,false);
}
g.drawImageTransformed (knobMask, x, y, width, height, rotator.rotated ((float)sliderPosProportional*rotaryEndAngle, (float)(knobMask->getWidth()/2), (float)(knobMask->getHeight()/2)), false);
}
i do this here
the knobs are actually one PNG that’s rotated and has a mouseOver state
There is a reason. If you have high requirements on the quality of your GUI controls, then you want to render them in a 3D animation tool, so they include shadows and perhaps a light source which shines from a certain angle. As the knob is turned, these properties should of course remain intact and they should not be rotated. That gives a much more professional look and feel to the user interface.
Probably not the best way. Look at the BinaryBuilder as an option for embedding the images into the actual code. The JuceDemo shows how to use the ImageCache class to access the binary object.
That sounds convoluted. The LookAndFeel methods will typically pass a Graphics reference onto which your image will be drawn. As such, typically, your LookAndFeel method would simply look something like
void genericLAFMethod(Graphics& g)
{
// Assuming image is an Image pointer that has been extracted from an ImageCache, or anywhere else.
g.drawImageAt(image, 0, 0)
}
You’ll need to handle that manually in the painter method.
[quote=“valley”]The LookAndFeel methods will typically pass a Graphics reference onto which your image will be drawn. As such, typically, your LookAndFeel method would simply look something like
void genericLAFMethod(Graphics& g)
{
// Assuming image is an Image pointer that has been extracted from an ImageCache, or anywhere else.
g.drawImageAt(image, 0, 0)
}
[/quote]
Yeah, it was something like that I looked for. Well, I guess I have to split my animations then. And use the drawImageAt method. Not too many, around 100+ frames stacked in each image :shock:
Split them? Surely the reason people use film strips is so you can have one image, and draw it at different y co-ordinates to reveal the frame that you want?
I would definitely recommend taking a few minutes to get to know the binary builder. Since it’ll process all images in a directory in one pass, and produce a single .cpp file for them, it’s going to be a huge time saver for stuff like this.
every component (a slider too) has a set of properties, add your own custom property to the slider and update it, this way you’ll have to values in the Slider class you can use to draw two values. Also there are two value and three value sliders, you can use those too i guess.
Split them? Surely the reason people use film strips is so you can have one image, and draw it at different y co-ordinates to reveal the frame that you want?[/quote]
Yeah, I think this one will do what I need:
void Graphics::drawImage ( const Image *const imageToDraw,
int destX,
int destY,
int destWidth,
int destHeight,
int sourceX,
int sourceY,
int sourceWidth,
int sourceHeight,
const bool fillAlphaChannelWithCurrentBrush = false
)
That would allow drawing portions of a source image into a destination image.
Apparently there is a nice tool called http://www.g200kg.com/en/software/knobman.html on kvr there is a lot of examples of knobs, and i understood why a film strip slider could work. wrote a little class to handle this situation in a LookAndFeel call for drawRotarySlider
class FilmStripSlider
{
public:
FilmStripSlider (Image *_knobStrip);
void drawFrame (Graphics &g, int x, int y, int width, int height, Slider &slider);
private:
Image *knobStrip;
int frameCount;
int frameSize;
bool isVerticalStrip;
};
FilmStripSlider::FilmStripSlider (Image *_knobStrip) : knobStrip(_knobStrip)
{
if (knobStrip->getWidth() > knobStrip->getHeight())
{
frameCount = knobStrip->getWidth() / knobStrip->getHeight();
frameSize = knobStrip->getHeight();
isVerticalStrip = false;
}
else
{
frameCount = knobStrip->getHeight() / knobStrip->getWidth();
frameSize = knobStrip->getWidth();
isVerticalStrip = true;
}
}
/* thanks to anita for the math */
void FilmStripSlider::drawFrame (Graphics &g, int x, int y, int width, int height, Slider &slider)
{
const double div = slider.getMaximum() / frameCount;
double pos = (int)(slider.getValue() / div);
if (pos > 0)
pos = pos - 1;
if (width != height) /* scale */
{
x = (width / 2) - (height / 2);
width = height;
}
if (isVerticalStrip)
{
g.drawImage (knobStrip, x, y, width, height, 0, (int)(pos*frameSize), frameSize, frameSize, false);
}
else
{
g.drawImage (knobStrip, x, y, width, height, (int)(pos*frameSize), 0, frameSize, frameSize, false);
}
}
just give it a film strip of knobs and it will draw the right frame depending on the slider value.