Polygon testing for SDL_Surface?

In Windows I’ve been using the gdi32.dll for simple 2D point and click
things…
Specifically the CreatePolygonRgn() and PtInRegion() functions.

If you’ve never used them then they’re similar to the tags for
HTML…
that is if you click inside a polygon (given by a list of coords.) you go to
this page
if you click outside it then you stay wherever you are.

I was wondering if SDL has it’s own version of this to handle clicks on
SDL_Surface,
I could get by using SDL_Rect but that would be a pain.

Also is there a cross platform (at least Win, GNU/Linux, Mac)?
Because I want my prog. to be os friendly.

I could write my own functions but I really don’t want to reinvent the
wheel…

Thanks,
David.

In Windows I’ve been using the gdi32.dll for simple 2D point and click
things…
Specifically the CreatePolygonRgn() and PtInRegion() functions.

I don’t think this is implemented in SDL proper. You might want to
check out ParaGUI or something like that. I haven’t used any of these
libs my self but they look nice.

On the other hand, I’ve written some C++ classes that implement some
very simple UI stuff including what you are talking about. I’ve been
meaning to post the code on my web page but I have not done it
yet. I’ve attached the relevant header file (and another one you may
be interested in). If you are interested tell me and I’ll send you all
of it. The code is GPL (and ? Arthur Peters). Hope this helps you out.

-Arthur
-------------- next part --------------
#ifndef __BLITABLES_H
#define __BLITABLES_H 1

#include

#include “util.h”
#include “screen.h”

#if HAVE_SDL_SDL_H
#include <SDL/SDL_video.h>
#else
#include <SDL_video.h>
#endif

/**
The base class for all objects that can be blited to a CScreen object.

It is basicly a wraper around an SDL_Surface structure. In almost all cases
it can be treated as a SDL_Surface *.

You should use \Ref{CTile} and \Ref{CSprite} instead if you just
want to blit a few objects to the screen.
*/
class CBlitable
{
public:
CBlitable();

virtual ~CBlitable();

operator SDL_Surface *() { return image; }

/**
Load an image from a file. This uses SDL_image so it will load
several differant image formats. The alpha channel is
discarded. If you want a transparent image you should use
\Ref{CSprite}.
*/
void LoadImage(char *filename);

/**
Blit the SDL_surface to the target surface at position (x,y).
You are in charge of making sure that that area of the screen is
updated.
*/
inline void BlitTo(int x, int y, SDL_Surface *dest);

/**
Blit the SDL_surface to the target CScreen at position (x,y). I
I am will make sure that that area of the screen is updated.
*/
inline void BlitTo(int x, int y, CScreen &dest);

/**
Blit the SDL_surface to the target surface using destination rectangle destrect.
You are in charge of making sure that that area of the screen is
updated.
*/
inline void BlitTo(SDL_Rect *destrect, SDL_Surface *dest);

/**
Blit the SDL_surface to the target CScreen using destination rectangle destrect.
I am will make sure that that area of the screen is updated.
*/
inline void BlitTo(SDL_Rect *destrect, CScreen &dest);

/**
Blit the surface to the target CScreen. The position is defined
by this->x and this->y.

  I am will make sure that that area of the screen is updated.

*/
virtual void DrawTo(CScreen &dest);

/**
Blit the surface to the target surface. The position is defined
by this->x and this->y.

  You are in charge of making sure that that area of the screen is
  updated.

*/
virtual void DrawTo(SDL_Surface *dest);

/**
Is point (p_x, p_y) in the bounds of this surface? This is
defined as (x, y, surface.w, surface.h).

  @return true if the point is in, false if not.

*/
bool isPointIn(int p_x, int p_y);

/**
Derived classes which are animated should implement this.
*/
virtual void Update(int msecs) {}

/**
Compares surface by there zorder.
*/
bool operator<(CBlitable &other) { return zorder < other.zorder; }

SDL_Surface *operator->() { return image; }

Uint32 w() { return (*this)->w; }
Uint32 h() { return (*this)->h; }

/**
Return a CRect of the bounding rectangle of the surface.
*/
CRect GetRect() { return CRect(x, y, w(), h()); }

/**
The z-order of the surface. Higher numbers put the surface
infront of lower z-ordered surfaces.
*/
int zorder;

/**
The X position of the surface on the screen in pixels.
*/
float x;

/**
The Y position of the surface on the screen in pixels.
*/
float y;
protected:
SDL_Surface *image;
};

/**
A blitable that is nothing. \emph{Can’t remember why I wrote this.}
*/
class CNullBlitable : public CBlitable
{
public:

// This is for inlining reasons. Yes, it should be lower down.
/**
Set the size of the nothingness.
*/
void SetSize(int width, int height)
{ image->h = height; image->w = width; }

CNullBlitable() { image = new SDL_Surface; }
CNullBlitable(int _x, int _y, int _w, int _h)
{
image = new SDL_Surface;
SetSize(_w, _h);
x = _x;
y = _y;
}

virtual ~CNullBlitable() { delete image; }

/**
No-op to replace the normal blit function.
/
void DrawTo(CScreen &dest) {}
/
*
No-op to replace the normal blit function.
*/
void DrawTo(SDL_Surface *dest) {}
};

/**
A blitable object that has a motion vector. Also (maybe more
importantly) when it loads an image it loads it with
transparency.
*/
class CSprite: public CBlitable
{
public:
CSprite();

/**
Load an image in to the surface at construction time.

  @see CSprite::LoadImage()

*/
CSprite(char *filename);

virtual ~CSprite();

/**
Load an image from a file. This uses SDL_image so it will load
several differant image formats. Unlike CBlitable::LoadImage the
alpha channel of the image is not discarded. If the image has an
alpha channel that is used, if not the upper left hand pixel is
used as the colorkey.
*/
void LoadImage(char *filename);

/**
Update the surface’s position by msecs milliseconds. The motion
vector is (this->dx, this->dy).
*/
void Update(int msecs);

/**
The speed at which the sprite should move on the X axis in pixels per second.
*/
float dx;

/**
The speed at which the sprite should move on the Y axis in pixels per second.
*/
float dy;
};

/**
The generic class for opaque surfaces.
*/
class CTile: public CBlitable
{
public:
CTile();

/**
Load an image in to the surface at construction time.

  @see CBlitable::LoadImage()
*/

CTile(char *filename);

virtual ~CTile();
};

/**
The class that should be used to organize a bunch of CBlitables. It
provides functions to draw all objects to the screen, call Update
on all objects, and blit the backgound over all objects.
*/
class CBlitableList
{
slist<CBlitable *> L;

CTile *Background;
CScreen *Screen;

//CSprite Cursor;

//bool doMouse;

class CompCBlitableP // Binary Predicate
{
public:
bool operator ()(CBlitable v1, CBlitable v2)
{
return v1->zorder < v2->zorder;
}
};
public:
/

You must provide the CBlitaleList with a CScreen to blit to and
a CTile as a background. These will be used in all the drawing
calls to this class.
*/
CBlitableList(CScreen *_screen = NULL, CTile *_background = NULL);

/**
Add an CBlitable object to the class. In future drawing calls it will be
drawn.
/
void Add(CBlitable item) { L.push_front(item); L.sort(CompCBlitableP()); }
/

Remove an CBlitable object from the class. It will no longer be drawn. You
can deallocate it.
*/
void Remove(CBlitable *item) { L.remove(item); }

/**
Draw all CBlitable objects in the class to the CScreen object.
This is done by iterating through the list calling DrawTo on
each object.
*/
void Render();

/**
Blit the background over all CBlitable objects in the class to
the CScreen object. This is done by iterating through the list
bliting a the proper chunk of the background over each object.
*/
void Clean();

/**
Update the position of all CBlitable objects in the class.
*/
void Update(Uint32 time);

/**
Force a complete redraw by bliting the whole background to the
whole screen.
*/
void ForceRedraw();

/**
Find out which CBlitable object the point (p_x, p_y) is in.
*/
CBlitable *inWhich(int p_x, int p_y);

/**
Set what background should be used.
*/
void SetBackground(CTile *_background) { Background = _background; }

/**
Set what screen should be drawn to.
*/
void SetScreen(CScreen *_screen) { Screen = _screen; }

//int ShowMouse(bool val);
};

#endif // ifndef __BLITABLES_H

-------------- next part --------------
#ifndef __GUI_H
#define __GUI_H 1

#include “blitables.h”

#if HAVE_SDL_SDL_H
#include <SDL/SDL_video.h>
#else
#include <SDL_video.h>
#endif

#if HAVE_SDL_SDL_TTF_H

include <SDL/SDL_ttf.h>

#else // probably HAVE_SDL_TTF_H

include <SDL_ttf.h>

#endif

/**
This class creates a button in it’s surface using a backgound image
and a text string.
*/
class CButton: public CTile
{
public:
CButton(char *_text, TTF_Font *_font, SDL_Color _color,
SDL_Surface *_template, int _width = -1);

void Build(char *_text, TTF_Font *_font, SDL_Color _color,
SDL_Surface *_template, int _width = -1);

void SetPosition(int _x, int _y) { x = _x; y = _y; };
//bool isPointIn(int p_x, int p_y);
};

/**
This class renders a string it to it’s surface.
*/
class CText: public CBlitable
{
public:
CText(char *_text, TTF_Font *_font, const SDL_Color &_color)
{ SetText(_text, _font, _color); }
CText();

void SetText(char *_text, TTF_Font *_font, const SDL_Color &_color);
};

#endif // ndef __GUI_H
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20001119/419ae06f/attachment.pgpFrom: xdavidx@flashmail.com (David A. Redick)
Subject: [SDL] polygon testing for SDL_Surface?
Date: Sat, 18 Nov 2000 23:14:56 -0800

In Windows I’ve been using the gdi32.dll for simple 2D point and click
things…
Specifically the CreatePolygonRgn() and PtInRegion() functions.
[…]
Also is there a cross platform (at least Win, GNU/Linux, Mac)?
Because I want my prog. to be os friendly.

SDL will receive and send you any mouse event taking place on its screen,
so “OS friendliness” has nothing to do with it.

I could write my own functions but I really don’t want to reinvent the
wheel…

No, there is no functions for that in SDL, and there is no reason there
should be. Write it yourself, it’s trivial (unless you have a very large
number of polygons and tight runtime requirements - then it starts to get
interesting). I don’t think there is a “point-in-polygon processor” in
common hardware that would speed up the operation immensely