Sign in to follow this  
Sceletor

Implementing non-rectangular windows in a SDL GUI

Recommended Posts

Sceletor    139
Does anybody here have some experience on implementing a gui in SDL that supports non-rectangular windows? I just read that SDL only has rects and now Im asking myself if its at all possible to create non-rectangular windows and checking for input in them. And if it is possible, where can I find some tutorials or information on it? Im lacking an idea, and google and forums search had no relevant hits [sad]

Share this post


Link to post
Share on other sites
Jaiminho    184
You mean windows with irregular frames, as if there it was created with no frames and had some transparency on background? If it's the case, then I think they were thinking about implementing that on SDL 1.3, since it can't be done yet.

Share this post


Link to post
Share on other sites
evillive2    779
Can you be more specific when you say "non-rectangular"?

Also, could you be more specific as to if you mean the main window or just the GUI elements inside?

Share this post


Link to post
Share on other sites
Sceletor    139
I only mean gui elements inside, not the main window itself.

Here is an example of what I intend to put on screen (as you can see, not really rectangular):

Panel

Oh, and before somebody reminds me that the hotspots of this menu indeed are rectangular:
Clicking the window to activate it requires that I have a solution for checking the whole window if a mouseevent happens..

Share this post


Link to post
Share on other sites
CodeMunkie    805
It should be pretty straight forward to do. With rectangular widgets you just test to see if the cursor position is inside the rectagular bounds of the widget. In the case of "non-rectangular" widgets, you do one additional test to make sure the pixel under the cursor position is a non-transparent color. So:

if(widget.containsPoint(cursor.x, cursor.y) && widget.getPixel(cursor.x, cursor.y)!=widget.getTransparentColor())
{
widget.fireMouseOverEvent();
}

Share this post


Link to post
Share on other sites
Sceletor    139
Okay, and are there some functions in SDL which make it easier to check for transparent color?
Im using .pngs and SDL_Image, so the easiest way with a normal color set to transparent and then just checking for this color shouldnt work.

Can SDL "detect" the alpha channel with some function?

Share this post


Link to post
Share on other sites
evillive2    779
SDL does not provide any "getpixel" or "setpixel" functions however you can use the SDL documentation to write your own. Once you have the pixel value you can use SDL_GetRGBA to get the individual color channels from it. For example this is taken from the SDL documentation which will answer most of your questions:

/*
* Return the pixel value at (x, y)
* NOTE: The surface must be locked before calling this!
*/

Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
return *p;

case 2:
return *(Uint16 *)p;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;

case 4:
return *(Uint32 *)p;

default:
return 0; /* shouldn't happen, but avoids warnings */
}
}


A better idea if you want to think in terms of "windows" is to actually use rectangles.
Panel
The green rectangle is where you start checking for mouse events in that particular window since that is the window holding all of the "controls". The red rectangles are the ones that actually do anything. If the initial check for the mouse position inside the green rectangle returns false then you don't check any further. If it returns true you check the control rectangles and act accordingly. Checking anything else is wasted in this case.

A simple parent->child relationship is key to making this work efficiently. Point in rectangle checking is relatively cheap but partitioning space in this way helps you eliminate unnecessary checks making it even more efficient.

Share this post


Link to post
Share on other sites
Zheo    148
Im my GUI I´ve discriminated between images with color key and images which have an Alpha channel.
bool GUI::ButtonImageWidget::isInside(SDL::SPoint p)
{

if (!GUI::Widget::isInside(p))
return false;

//Translate to Screen coordinate system
SDL::SPoint prel = getPosWidgetRelative(p);


//Surface uses a color key
if (_ptrCanvas->hasColorKey())
{
Uint32 color = _ptrCanvas ->getPixelColor(prel);
if (color == _ptrCanvas ->getColorKey())
return false;
}

//Surface has an alpha component (RGBA)
else if (_ptrCanvas ->hasAlphaComponent())
{

Uint8 alpha = _ptrCanvas ->getPixelColorComponent(prel,SDL::Video::Alpha);
//alpha is completely transparent
if (alpha == SDL::Video::SDL_TRANSPARENT)
return false;

}

return true;

}



getPixelColor() is similar to getPixel() function evillive2 posted before.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this