Implementing non-rectangular windows in a SDL GUI

Started by
6 comments, last by Zheo 16 years, 11 months ago
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]
Advertisement
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.
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?
Evillive2
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..
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();
}
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
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?
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.
Evillive2
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.

This topic is closed to new replies.

Advertisement