Author Topic: SOLVED: Ignoring transparent pixels on GUI Buttons for Click / Mouseover label  (Read 359 times)

Privateer Puddin'

  • Mittens Knight
  • bob
Hello,

I have a custom inventory GUI where I am using buttons for each item. On each button is an image, such as:



The issue being when I click

Code: Adventure Game Studio
  1. GUI.ProcessClick(mouse.x, mouse.y, eModeInteract);

or mouse over

Code: Adventure Game Studio
  1. (GUIControl.GetAtScreenXY(mouse.x, mouse.y);)

it takes into account the whole button, including the grey transparent area (unless I have another button on top z order wise)

Is there a way to ignore the transparent pixels?

I did search the forums and came across a couple of suggestions and wanted to know if these would be the route to go down, or if there's something better?

http://www.adventuregamestudio.co.uk/forums/index.php?topic=28882.msg367578#msg367578

http://www.adventuregamestudio.co.uk/forums/index.php?topic=44095.msg587336#msg587336 - I guess this one only works if the graphic is a certain shape

Thanks!
« Last Edit: 18 Apr 2018, 02:20 by Privateer Puddin' »

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
Yeah, AFAIK there's no built-in way. If you're using magic pink for transparency you could probably do a getpixel() on the sprite, but with alpha that gets more complicated.

The dummy character and pixel-perfect click detection hack is probably your best bet.

Privateer Puddin'

  • Mittens Knight
  • bob
I did take a quick look at the GetPixel stuff. Am I right in thinking it would return the pixel colour of any buttons behind it on the transparent section? Edit: No, it's picking up the colours from the room background behind the GUI

In theory, if my inv items was made up of three (unique? does it matter if I'm doing the first btn check? and I know the button behind is 99% not going to match) colours, could I do something like...

Code: Adventure Game Studio
  1. if (theControl == btnHose) && ((surface.GetPixel(mouse.X, mouse.Y)) == COLOURA / COLOURB / COLOURC)   //mouse is over button, and not a transparent pixel
  2.  lblHotspot.Text = "Hose";
  3. } else {
  4. // do nothing, since it's not over button / transparent pixel
  5. }
  6.  
(I know the operator bit isn't right)

« Last Edit: 17 Apr 2018, 06:32 by Privateer Puddin' »

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
I meant GetPixel() on the sprite itself, or rather, on its DrawingSurface. Copy the sprite to a DynamicSprite, get a  DrawingSurface for it, and call GetPixel().

Privateer Puddin'

  • Mittens Knight
  • bob
Right! I'm not very good with DrawingSurface etc. so I've given this a go, and it seems to work..

Code: Adventure Game Studio
  1. if (theControl == btnLunchbox) { //mouseover lunchbox inv item
  2.     DynamicSprite* sprite = DynamicSprite.CreateFromExistingSprite(1183, false); //store sprite of inv item with pink bg no transparancy
  3.     DrawingSurface *surface = Room.GetDrawingSurfaceForBackground(); //draw surface
  4.     surface.DrawImage(btnLunchbox.X, btnLunchbox.Y, sprite.Graphic); //draw inv item on surface
  5.       if (surface.GetPixel(mouse.x, mouse.y) == 63519) { //check if mouse is over pink transparency colour
  6.         btnLunchbox.NormalGraphic = 1125; // set normal version of inv item graphic
  7.         lblHotspot.Text = ""; // clear label
  8.         surface.Release();
  9.         sprite.Delete();
  10.       } else {
  11.         btnLunchbox.NormalGraphic = 1126; //mouse is over inv item, so set mouseover graphic
  12.         lblHotspot.Text = "Lunchbox"; //mouse is over inv iem, so set label
  13.       }
  14.  

I'm also putting the  btnLunchbox.NormalGraphic = 1125; when mouse is over no buttons

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
You got it. I'd personally refactor it as a standalone function taking the sprites you want to detect and the button versions as parameters,but you have the logic of it.

Privateer Puddin'

  • Mittens Knight
  • bob
Broke something, will update!
« Last Edit: 17 Apr 2018, 08:53 by Privateer Puddin' »

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
Another thing you'll need to do is to calculate the x,y coordinates relative to the spite, not just use mouse.x/y. In practice this means you subtract (Button.X/Y + Button.OwningGUI.X/Y) from mouse.x/y.

Privateer Puddin'

  • Mittens Knight
  • bob
Hm, how come I need to do that?

This is basically on the same code I posted earlier (in terms of anything mentioning mouse.x)



« Last Edit: 18 Apr 2018, 02:21 by Privateer Puddin' »

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
Oh, looking more closely at your code, you did it a little differently than I meant (by getting a drawingsurface for the background, which I think is a bad idea: here it looks like you're actually drawing the button sprite to the background, surely not the intention). Still, even with your approach it should only work at all if the GUI is full-screen (or at least, located at 0,0.

Privateer Puddin'

  • Mittens Knight
  • bob
Yeah, I came across that earlier and 'fixed' it but I'm sure is bad but it's all I could get to work :p

I didn't realise what was happening at first, because I was testing on the Lunchbox inventory item, which is sat squarely on the bag gui button and hadn't turned the inventory off. Only when I started tested on the rope did I realise I was drawing on to the background. So, here's what I have at the moment. I tried a function as well (I'm not very good with either functions or drawingsurface, a lot of the manual stuff goes over my head).

Code: Adventure Game Studio
  1. function InvUpdate(Button *btnName, String description,  int sprite_number_nontrans, int sprite_number_normal, int sprite_number_mouseover) {
  2.   DrawingSurface *backgroundCopy2;
  3.   DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();  
  4.   if (backgroundCopy2 == null) backgroundCopy2 = surface.CreateCopy(); // first time, create back-up copy of background
  5.   else surface.DrawSurface(backgroundCopy2); // restore previous background
  6.   DynamicSprite* sprite = DynamicSprite.CreateFromExistingSprite(sprite_number_nontrans, false); //store sprite of inv item with pink bg no transparancy
  7.   //DrawingSurface *surface = sprite.GetDrawingSurface();  // I tried using this at one point?
  8.   surface.DrawImage(btnName.X, btnName.Y, sprite.Graphic); //draw inv item on surface
  9.     if (surface.GetPixel(mouse.x, mouse.y) == 63519) { //check if mouse is over pink transparency colour
  10.     OverInv = false;
  11.       btnName.NormalGraphic = sprite_number_normal; // set normal version of inv item graphic
  12.       lblHotspot.Text = ""; // clear label
  13.       surface.Clear();
  14.       surface.DrawSurface(backgroundCopy2);
  15.       surface.Release();
  16.       sprite.Delete();
  17.     } else {
  18.       surface.Clear();
  19.       surface.DrawSurface(backgroundCopy2);
  20.       surface.Release();
  21.        
  22.       sprite.Delete();
  23.       btnName.NormalGraphic = sprite_number_mouseover; //mouse is over inv item, so set mouseover graphic
  24.       lblHotspot.Text = description; //mouse is over inv iem, so set label
  25.       OverInv = true;
  26.     }
  27. }
  28.  

Which I call with

Code: Adventure Game Studio
  1. InvUpdate(btnRope, "Rope", 1184, 1129, 1130);

and yeah, my GUI is full screen.

Snarky

  • Global Moderator
  • Mittens Earl
  • Private Insultant
    • I can help with proof reading
    •  
    • I can help with translating
    •  
Try this, man:

Code: Adventure Game Studio
  1. bool MouseOverPixelPerfect(this Button*, int mouseOverGraphic, String label)
  2. {
  3.   // Calculate mouse coordinates relative to button sprite canvas
  4.   int x = mouse.x - this.X - this.OwningGUI.X;
  5.   int y = mouse.y - this.Y - this.OwningGUI.Y;
  6.  
  7.   // Get the color on button sprite canvas at mouse cursor pixel
  8.   DynamicSprite* buttonMask = DynamicSprite.CreateFromExistingSprite(this.NormalGraphic, false);
  9.   DrawingSurface* maskSurface = buttonMask.GetDrawingSurface();
  10.   int pixelColor = maskSurface.GetPixel(x,y);
  11.   maskSurface.Release();
  12.   buttonMask.Delete();
  13.  
  14.   if(pixelColor == COLOR_TRANSPARENT) // if this doesn't work then try your harcoded number, 63519
  15.   {
  16.     // Transparent, so don't highlight
  17.     this.MouseOverGraphic = this.NormalGraphic;
  18.     lblHotspot.Text = "";
  19.     return false;
  20.   }
  21.   // Otherwise, highlight
  22.   lblHotspot.Text = label;
  23.   this.MouseOverGraphic = mouseOverGraphic;
  24.   return true;
  25. }

Call it like:

Code: Adventure Game Studio
  1. if (theControl == btnRope)
  2.   btnRope.MouseOverPixelPerfect(1130, "Rope");

Privateer Puddin'

  • Mittens Knight
  • bob
Hey! That works just as well as mine ;)

Thanks a lot for your help Snarky - Solved!