|
Check if the mouse is over irregular shapes |
shadyvillian
Member #12,426
December 2010
|
I'm trying to fancy up my ui in one of my programs and wanted to use other shapes than just squares and rectangles. But I'm having problems with the code crashing. Does this look like a good way to do it? 1void Framework_SelectableButton::RegisterIrregularShape()
2{
3 IrregularShape = true;
4 vector<vector<ALLEGRO_COLOR>> Pixels(al_get_bitmap_height(UpImage), vector<ALLEGRO_COLOR>(al_get_bitmap_width(UpImage)));
5 al_lock_bitmap(UpImage, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
6
7 for(int i = 0; i < al_get_bitmap_height(UpImage); i++)
8 {
9 for(int j = 0; j < al_get_bitmap_width(UpImage); j++)
10 {
11 Pixels[i][j] = al_get_pixel(UpImage, i, j);
12 }
13 }
14
15 al_unlock_bitmap(UpImage);
16 ImagePixels = Pixels;
17}
1void Framework_SelectableButton::IsMouseOver(int MouseX, int MouseY)
2{
3 if(IrregularShape == false)
4 {
5 if((MouseX >= x1) && (MouseX <= x2) && (MouseY >= y1) && (MouseY <= y2))
6 {
7 Over = true;
8 }
9
10 else
11 {
12 Over = false;
13 }
14 }
15
16 else if(IrregularShape == true)
17 {
18 if((MouseX >= x1) && (MouseX <= x2) && (MouseY >= y1) && (MouseY <= y2)) //check if the mouse is over the image at all
19 {
20 unsigned char r, g, b, alpha;
21 al_unmap_rgba(ImagePixels[MouseX-x1][MouseY-y1], &r, &g, &b, &alpha);
22
23 if(alpha == 0)
24 {
25 Over = false;
26 }
27
28 else // if the pixel that the mouse is over isnt completly transparent then over is true
29 {
30 Over = true;
31 }
32 }
33
34 else
35 {
36 Over = false;
37 }
38 }
39}
Heres EDIT: I've attached what one of the images look like. Its pretty much looks like a quarter part of an o. Software Engineer by day, hacker by night. |
Arthur Kalliokoski
Second in Command
February 2005
|
It seems to me that the active area for a mouse is still rectangular even if the widget is oval or whatever. It'd be rather hard to notice this unless your OCD or something. They all watch too much MSNBC... they get ideas. |
jmasterx
Member #11,410
October 2009
|
It probably crashes because: for(int i = 0; i < al_get_bitmap_height(UpImage); i++) { for(int j = 0; j < al_get_bitmap_width(UpImage); j++) { Pixels[i][j] = al_get_pixel(UpImage, i, j); } } should probably be: for(int j = 0; j < al_get_bitmap_height(UpImage); j++) { for(int i = 0; i < al_get_bitmap_width(UpImage); i++) { Pixels[i][j] = al_get_pixel(UpImage, i, j); } } But really, why store every pixel? Just translate the mouse so that it is relative to the bitmap eg: if bitmap is at 50,50 subtract 50,50 from mouse position. But if you want to do it your way, remember c++ is row major so [width][height] Agui GUI API -> https://github.com/jmasterx/Agui |
shadyvillian
Member #12,426
December 2010
|
Yeah thats what I figured was causing the crash. I just wanted to store all the pixels because I thought that if the mouse is moved alot over the image that all the al_get_pixel calls would cause lag. EDIT: The code seems to work fine. Its pixel perfect precision. But after I click on one button and then click on another on it crashes on al_unmap_rgba(ImagePixels[x][y], &r, &g, &b, &alpha); EDIT2: Changing the code to this stops the crashes unsigned char r, g, b, alpha; al_unmap_rgba(al_get_pixel(UpImage, MouseX-x1, MouseY-y1), &r, &g, &b, &alpha); Over = true; if(alpha == 0) // if the pixel that the mouse is over is completly transparent then over is false { Over = false; } Will locking the bitmap in this situation increase performance?(between the unmap_rgba) Software Engineer by day, hacker by night. |
jmasterx
Member #11,410
October 2009
|
I don't think so. I think the cost of locking it so often would outweigh the performance boost. Agui GUI API -> https://github.com/jmasterx/Agui |
Trent Gamblin
Member #261
April 2000
|
Locking would probably help unless you're only doing a few pixels. Just make sure to only lock the region you need if it's not the whole bitmap. Sorry, I didn't really read your code so I don't know what's best for you, just that locking helps if you're accessing more than a few pixels and they're all adjacent.
|
shadyvillian
Member #12,426
December 2010
|
Well al_get_pixel is called everytime an allegro_event_mouse_axes event occurs and the mouse is over the bitmap. Software Engineer by day, hacker by night. |
Trent Gamblin
Member #261
April 2000
|
If it's just called once then it doesn't matter if you lock the bitmap. The way it works is, al_get_pixel will lock a 1x1 pixel region of the bitmap for you if the bitmap isn't locked already. Then it will unlock it. If it is already locked, it just reads from the lock data and doesn't unlock the bitmap. If you get a pixel outside of the locked region it will return 0s for the pixel data. So for 1 pixel the behaviour is identical. For more than 1 pixel you can avoid locking operatings in al_get_pixel by locking yourself which will be faster, because locking is slow.
|
|