A quick and possibly dumb question, is there a way to draw a image which is repeated/tiled in an area? If not, I will create my own code and share here.
Wk
A quick and possibly dumb question, is there a way to draw a image which is repeated/tiled in an area? If not, I will create my own code and share here.
Wk
Graphics::setTiledImageFill
Oh man, I need to learn how to do better searchesā¦ :oops:
Thanks Jules.
Wk
Actually, thereās nothing like this in the online manual. I couldnāt find it in Juce files either. I will check if thereās a newer Juce version, it could be that. (Iām using 1.50)
Wk
Strange, thereās no newer version, so it seems Iām using the latest.
I did find āImageBrushā which seems to be what Iām looking:
[code]/**
A Brush that fills areas with tiled repetitions of an image.
@see Brush, Graphics::setBrush, SolidColourBrush, GradientBrush
*/
class JUCE_API ImageBrush : public Brush[/code]
Wk
Thanks, its what I mentioned above, Iām already using it. 8)
g.setBrush(backBrush);
g.fillRect(0,0,getWidth(),getHeight());
Wk
Hereās the code I created to draw a skinable square. It used 9 Images.
[code] if (Background[0] != 0)
{
if (backBrush[0] == 0)
{
backBrush[0] = new ImageBrush(Background[1],0,0,1.0f);
backBrush[1] = new ImageBrush(Background[3],0,0,1.0f);
backBrush[2] = new ImageBrush(Background[4],0,0,1.0f);
backBrush[3] = new ImageBrush(Background[5],getWidth()-Background[5]->getWidth(),0,1.0f);
backBrush[4] = new ImageBrush(Background[7],0,getHeight()-Background[7]->getHeight(),1.0f);
}
g.setBrush(backBrush[2]); // Middle ///
g.fillRect(0,0,getWidth(),getHeight());
g.setBrush(backBrush[0]); // Top Middle //
g.fillRect(0,0,getWidth(),Background[1]->getHeight());
g.setBrush(backBrush[4]); // Bottom Middle //
g.fillRect(0,getHeight()-Background[7]->getHeight(),getWidth(),Background[7]->getHeight());
g.setBrush(backBrush[1]); // Left Middle //
g.fillRect(0,Background[0]->getHeight(),Background[3]->getWidth(),getHeight()-Background[0]->getHeight()-Background[6]->getHeight());
g.setBrush(backBrush[3]); // Right Middle //
g.fillRect(getWidth()-Background[5]->getWidth(),Background[2]->getHeight(),Background[5]->getWidth(),getHeight()-Background[2]->getHeight()-Background[8]->getHeight());
g.drawImageAt(Background[0],0,0);
g.drawImageAt(Background[2],getWidth()-Background[2]->getWidth(),0);
g.drawImageAt(Background[6],0,getHeight()-Background[6]->getHeight());
g.drawImageAt(Background[8],getWidth()-Background[8]->getWidth(),getHeight()-Background[8]->getHeight());
}[/code]
It uses Image Background[9] which are: TopLeft,TopMid,TopRight,MidLeft,MidMid,MidRight,BottLeft,BottMid,BottRight.
The Brush are:
ImageBrush* backBrush[5];
Wk
If thereās a resize, just delete all backBrush variables and repaint, thatās all. Seems to be working hereā¦
Wk
Ah, yes, sorry - Iām in the middle of changing all the graphics context filling stuff, so donāt get carried away with ImageBrushes, as theyāre going to be deprecated at some point in the future.
The new Graphics::setTiledImageFill method isnāt in the online docs yet, but is there in the headers if youāve got the latest code. It does basically the same thing, but will allow more efficient rendering than is possible by using the abstract Brush classes.
Thanks Jules. I just downloaded the latest version and I see it now in the header files. (I didnāt know how to download the daily/weekly files)
But now I wonder, the setBrush works correctly like I need, while setTiledImageFill doesnāt.
I want to create my own Background image which can be resized, so with any window size it will look correctly thanks to the 9 images as Iām using above.
Now, with setTiledImageFill, from what I understood, I only got to use One picture for the entire background, is that correct?
So, am I right to say that only Brushes would do the correct thing in this case? I do worry that you will deprecate it, since it works perfectly for what Iām doing. But I understand, just need to find another way to do what I have in mind.
Wk
ā¦no, they have exactly the same capability. Youād just call setTiledImageFill instead of setBrush. It actually makes for more readable code, and avoids having to worry about deleting your brush objects (though in your example thatās clearly not a worry for you, as you seem to just be leaking them!)
Oh, ok, I understand now, I will try it out. Thanks Jules. 8)
Wk
Yeah, it works perfectly. Thanks again.
Hereās the new code. Maybe I will try to create a Macro for this, as its very handy.
[code]void FileTreeMain::paint (Graphics& g)
{
if (Background[0] != 0)
{
g.setTiledImageFill(*Background[4],0,0,1.0f); // Middle ///
g.fillRect(0,0,getWidth(),getHeight());
g.setTiledImageFill(*Background[1],0,0,1.0f); // Top Middle //
g.fillRect(0,0,getWidth(),Background[1]->getHeight());
g.setTiledImageFill(*Background[7],0,getHeight()-Background[7]->getHeight(),1.0f); // Bottom Middle //
g.fillRect(0,getHeight()-Background[7]->getHeight(),getWidth(),Background[7]->getHeight());
g.setTiledImageFill(*Background[3],0,0,1.0f); // Left Middle //
g.fillRect(0,Background[0]->getHeight(),Background[3]->getWidth(),getHeight()-Background[0]->getHeight()-Background[6]->getHeight());
g.setTiledImageFill(*Background[5],getWidth()-Background[5]->getWidth(),0,1.0f); // Right Middle //
g.fillRect(getWidth()-Background[5]->getWidth(),Background[2]->getHeight(),Background[5]->getWidth(),getHeight()-Background[2]->getHeight()-Background[8]->getHeight());
g.drawImageAt(Background[0],0,0);
g.drawImageAt(Background[2],getWidth()-Background[2]->getWidth(),0);
g.drawImageAt(Background[6],0,getHeight()-Background[6]->getHeight());
g.drawImageAt(Background[8],getWidth()-Background[8]->getWidth(),getHeight()-Background[8]->getHeight());
}
}[/code]
Wk
And hereās the Macro.
// IMAGE must be "Image* image[9]" Nine Pictures in the following order:
// (TopLeft,TopMid,TopRight,MidLeft,MidMid,MidRight,BottomLeft,BottomMid,BottomRight)
#define skinDrawSquare(IMAGE,X,Y,WIDTH,HEIGHT); \
\
g.setTiledImageFill(*IMAGE[4],X,Y,1.0f); \
g.fillRect(X,Y,WIDTH,HEIGHT); \
\
g.setTiledImageFill(*IMAGE[1],X,Y,1.0f); \
g.fillRect(X,Y,WIDTH,IMAGE[1]->getHeight()); \
\
g.setTiledImageFill(*IMAGE[7],X,Y+HEIGHT-IMAGE[7]->getHeight(),1.0f); \
g.fillRect(X,Y+HEIGHT-IMAGE[7]->getHeight(),WIDTH,IMAGE[7]->getHeight()); \
\
g.setTiledImageFill(*IMAGE[3],X,Y,1.0f); \
g.fillRect(X,Y+IMAGE[0]->getHeight(),IMAGE[3]->getWidth(),HEIGHT-IMAGE[0]->getHeight()-IMAGE[6]->getHeight()); \
\
g.setTiledImageFill(*IMAGE[5],X+WIDTH-IMAGE[5]->getWidth(),Y,1.0f); \
g.fillRect(X+WIDTH-IMAGE[5]->getWidth(),Y+IMAGE[2]->getHeight(),IMAGE[5]->getWidth(),HEIGHT-IMAGE[2]->getHeight()-IMAGE[8]->getHeight()); \
\
g.drawImageAt(IMAGE[0],X,Y); \
g.drawImageAt(IMAGE[2],X+WIDTH-IMAGE[2]->getWidth(),Y); \
g.drawImageAt(IMAGE[6],X,Y+HEIGHT-IMAGE[6]->getHeight()); \
g.drawImageAt(IMAGE[8],X+WIDTH-IMAGE[8]->getWidth(),Y+HEIGHT-IMAGE[8]->getHeight());
And hereās an example of usage:
void FileTreeMain::paint (Graphics& g)
{
if (Background[0] != 0)
{
skinDrawSquare(Background,0,0,getWidth(),getHeight());
}
}
Where Background is Image* Background[9];
Wk
Hereās a Macro that will draw Transparent images, with an Opacity option:
[code]/*
Image* buttonIMAGE[9];
Starting from the Top-Left Corner. Its best that all images have the same size, or relative sizes.
0 1 2
3 4 5
6 7 8
*/
#define skinDrawSquare(IMAGE,X,Y,WIDTH,HEIGHT,OPACITY);
g.setTiledImageFill(*IMAGE[4],X+IMAGE[3]->getWidth(),Y+IMAGE[1]->getHeight(),OPACITY);
g.fillRect(X+IMAGE[3]->getWidth(),Y+IMAGE[1]->getHeight(),WIDTH-IMAGE[3]->getWidth()-IMAGE[5]->getWidth(),HEIGHT-IMAGE[1]->getHeight()-IMAGE[7]->getHeight());
g.setTiledImageFill(*IMAGE[1],X+IMAGE[0]->getWidth(),Y,OPACITY);
g.fillRect(X+IMAGE[0]->getWidth(),Y,WIDTH-IMAGE[0]->getWidth()-IMAGE[2]->getWidth(),IMAGE[1]->getHeight());
g.setTiledImageFill(*IMAGE[7],X+IMAGE[6]->getWidth(),Y+HEIGHT-IMAGE[7]->getHeight(),OPACITY);
g.fillRect(X+IMAGE[6]->getWidth(),Y+HEIGHT-IMAGE[7]->getHeight(),WIDTH-IMAGE[6]->getWidth()-IMAGE[8]->getWidth(),IMAGE[7]->getHeight());
g.setTiledImageFill(*IMAGE[3],X,Y+IMAGE[0]->getHeight(),OPACITY);
g.fillRect(X,Y+IMAGE[0]->getHeight(),IMAGE[3]->getWidth(),HEIGHT-IMAGE[0]->getHeight()-IMAGE[6]->getHeight());
g.setTiledImageFill(*IMAGE[5],X+WIDTH-IMAGE[5]->getWidth(),Y,OPACITY);
g.fillRect(X+WIDTH-IMAGE[5]->getWidth(),Y+IMAGE[2]->getHeight(),IMAGE[5]->getWidth(),HEIGHT-IMAGE[2]->getHeight()-IMAGE[8]->getHeight());
g.setTiledImageFill(*IMAGE[0],X,Y,OPACITY);
g.fillRect(X,Y,IMAGE[0]->getWidth(),IMAGE[0]->getHeight());
g.setTiledImageFill(*IMAGE[2],X+WIDTH-IMAGE[2]->getWidth(),Y,OPACITY);
g.fillRect(X+WIDTH-IMAGE[2]->getWidth(),Y,IMAGE[2]->getWidth(),IMAGE[2]->getHeight());
g.setTiledImageFill(*IMAGE[6],X,Y+HEIGHT-IMAGE[6]->getHeight(),OPACITY);
g.fillRect(X,Y+HEIGHT-IMAGE[6]->getHeight(),IMAGE[6]->getWidth(),IMAGE[6]->getHeight());
g.setTiledImageFill(*IMAGE[8],X+WIDTH-IMAGE[8]->getWidth(),Y+HEIGHT-IMAGE[8]->getHeight(),OPACITY);
g.fillRect(X+WIDTH-IMAGE[8]->getWidth(),Y+HEIGHT-IMAGE[8]->getHeight(),IMAGE[8]->getWidth(),IMAGE[8]->getHeight());[/code]
out of curiosity, why a macro and not a static C function ?
Ah, good question. Its just that I donāt know how I would do a static function for that. Iām pretty sure I could figure it out. Maybe someone could show to me how to do that? :mrgreen: Iām still learning, every day. :oops:
Wk
Or a class that holds the images and has a ādraw (Graphics& g)ā method?