[SOLVED] Clicking a few times on GUI button makes it disappear

Started by MonkeySyrup, Mon 16/03/2020 19:06:51

Previous topic - Next topic

MonkeySyrup

Problem is in the subject. I don't know if it actually disappears or just somehow changes it's position, but maybe someone knows why it happens?

Here's my simple function:
Code: ags
function book1_OnClick(GUIControl *control, MouseButton button)
{
  if(book1.NormalGraphic == 0)
      book1.NormalGraphic = 128;
  else
      book1.NormalGraphic = 0;
}

Slasher

Isn't Graphic 0 the small blue cup?

Try making book1.NormalGraphic==Change to another graphic number of image you want to show

MonkeySyrup

Looks like it works with another graphic number, but why doesn't it work with Graphic 0? And no, it's not blue cup, Graphic 0 just makes it invisible/transparent. Is it possible that changing graphic number to 0 makes the button really small?

Slasher

Button graphic 0 sets button graphic as null..

Glad it works ok now though...

ManicMatt

Would using the visible = true; code work? (Probably not)

Or importing an empty sprite with the same dimensions? I can't think of an instance where the player would want to click on something invisible in a GUI, so i'm curious what it is you're trying to achieve?

MonkeySyrup

Quote from: ManicMatt on Tue 17/03/2020 09:34:09
Would using the visible = true; code work? (Probably not)

Or importing an empty sprite with the same dimensions? I can't think of an instance where the player would want to click on something invisible in a GUI, so i'm curious what it is you're trying to achieve?

I'm trying to create a GUI of bookshelf. When you click on a book, you pull a book out, that's when I change graphic number to 128. When I click on the same book one more time, you push the book in and the graphic number will be changed to 0

ManicMatt

#6
Why did you use a GUI for that? I'm guessing it's a close up of the bookshelf in a room and that's why you did it. I'd have it transition to another room personally, and I would have hotspots and objects for the books, and have the book image turn visible or invisible depending on a variable or if the image is currently visible when clicking on the hotspot.

Edit: i didn't fully absorb what you last said, sorry.

MonkeySyrup

I understand that your approach is better, but I wanted to do it like in this photo (one place zoomed in, but you can still see the main room):
Spoiler
[close]

And I thought that GUI would be a better approach. I'll change it to room if the GUI approach won't work as I want it to

Crimson Wizard

#8
Quote from: MonkeySyrup on Tue 17/03/2020 09:07:18
Looks like it works with another graphic number, but why doesn't it work with Graphic 0? And no, it's not blue cup, Graphic 0 just makes it invisible/transparent. Is it possible that changing graphic number to 0 makes the button really small?

Button logic is that if you set its NormalGraphic to 0, then it supposed to display default button looks (a grey rectangle with shadow around it) with a text.

I cannot tell why does it become completely invisible though... maybe it's Width & Height are really small? but then, how were you able to click on it in the first place? hmm...

MonkeySyrup

But if I set Image to 0 on GUI, it just shows 4 red rectangles in button corners, and that's what I want. Does it mean that Image and NormalGraphic is not the same thing?

Crimson Wizard

#10
Quote from: MonkeySyrup on Tue 17/03/2020 11:23:25
But if I set Image to 0 on GUI, it just shows 4 red rectangles in button corners, and that's what I want. Does it mean that Image and NormalGraphic is not the same thing?

Ah, right, if you also have Text set to empty string, it will not drawn anything at all. Red corners are only shown in the editor, letting you know where the button is.
Yes, Image in the editor, and NormalGraphic in the script, are exactly same thing.

Pardon me, I got little confused, could you explain again, does it not work as you like at the moment? I believe button should remain clickable even if it has NormalGraphic = 0, so long as Width and Height are proper.

MonkeySyrup

Yeah, I found a problem. When I change NormalGraphic to 0, the button becomes very small. I'll need to find another solution

Snarky

I'm not 100% clear on what you want to happen.

-If you have two different sprites you want to display in each state, just use a sprite index other than 0
-If you want the button to disappear, you can use the property Button.Visible (switch between true/false) instead of changing the sprite index (though of course, once the button is gone you can't click on it any longer)
-If you want the button to be invisible but still clickable, you can for example make a sprite that's completely transparent and set the NormalGraphic sprite index to that

Crimson Wizard

#13
Quote from: MonkeySyrup on Tue 17/03/2020 11:33:44
Yeah, I found a problem. When I change NormalGraphic to 0, the button becomes very small. I'll need to find another solution

Oh , I see. Problem is that when you change NormalGraphic to 0 in script, it also updates Width & Height to the size of sprite 0.
Try adjusting Width & Height properties to wanted values.

For example,
Code: ags
function book1_OnClick(GUIControl *control, MouseButton button)
{
  if(book1.NormalGraphic == 0)
  {
      book1.NormalGraphic = 128;
  }
  else
  {
      book1.NormalGraphic = 0;
      book1.Width = Game.SpriteWidth[128];
      book1.Height= Game.SpriteHeight[128];
  }
}

MonkeySyrup

#14
Thanks guys, you were very helpful. I'll probably go with changing Width & Height, because Snarky's solutions just wouldn't work for me:

-I have only one sprite
-I want it to be clickable even when it is invisible
-That's a good solution, but I have a lot of different size books, so I would need different transparent sprites. It's not worth doing that

Snarky

Fair enough!  :)

If you have a bunch of these books, for simplicity (and to reduce the risk of making some typo or other mistake somewhere) I would recommend making a helper function. I think something like this would work:

Code: ags
void SwitchVisible(this Button*, int bookSprite)
{
  if(this.NormalGraphic == 0)
  {
      this.NormalGraphic = bookSprite;
      this.PushedGraphic = 0;
  }
  else
  {
      this.NormalGraphic = 0;
      this.PushedGraphic = bookSprite;
      this.Width = Game.SpriteWidth[bookSprite];
      this.Height= Game.SpriteHeight[bookSprite];
  }
}

function book1_OnClick(GUIControl *control, MouseButton button)
{
   book1.SwitchVisible(128);
}

// And so on, for example...
function book2_OnClick(GUIControl *control, MouseButton button)
{
   book2.SwitchVisible(129);
}


That way the function for each book_OnClick() becomes a one-liner.

This solution stores the sprite index in Button.PushedGraphic when not in use, which I think should be OK. (The only difference should be that the book appears/disappears the moment you click the button down, rather than when you release it.) If not, you could add a custom property.

MonkeySyrup


TheManInBoots

Side note: Yes, normalGraphic corresponds to the image you see in the gui editor.

If I understood correctly, the above method works only with buttons that have text added to them (because of the transparent sprite), so I thought I'd add two more possible solutions here that can be considered for buttons without text:
Spoiler

When you click the book button, make it invisible.
e.g.:
Code: ags
book1.Visible=false;


Then you create a "On_Click" function for the entire Gui.
And in it you define the exact coordinates where the now invisible book button was placed before.

Code: ags
function gGuiShelf_OnClick(GUI *theGui, MouseButton button)
{
if(mouse.x>79 && mouse.x<140&&mouse.y>79&&mouse.y<131)//Here you calculate the exact coordinates of where the book was placed
book1.Visible=true;
}


So if you look what I did, when the entire gui is clicked, but only on the spot where the button usually is, the button/book will become visible again.
(You can calculate the exact button coordinates by adding it's lengths and offsets in it's property pane)

The second solution is to use the same approach as suggested in the thread above, but instead of using a transparent normalgraphic sprite it changes to, you use a sprite that is a cutout of the background.
For clarification:
The gui background:

The button:

The button on the background (background whitened for clarification):


Both solutions work reliably.
[close]

MonkeySyrup

Hm, your first solution requires a lot of hard coding and precision. Second solution is good, but I have 50 books, I would need 100 sprites only for one GUI, so now I have background of all the books and bookshelf and 50 sprites of pulled out books.

IMO, all solutions are quite good, but most of them just wouldn't work for me or they would require a lot more work.

TheManInBoots

Yeah, I can imagine it's too much work for what you're trying to do.
Btw. you could trick your way around not being able to click a transparent button, by having one pixel drawn on the original empty sprite (that you use the method Crimson Wizard suggested) with 0.1 opacity/transparency for that one pixel in the image editor you use, and the rest transparent. It's a little bit under the table advice, but in case nothing else works...

TheManInBoots

Btw. MonkeySyrup,
great news, I have made a module called "Button Magic" that does all that automatically!

So with the module all you will have to write is this when clicking on the entire Gui:

Code: ags

function gGuiShelf_OnClick(GUI *theGui, MouseButton button)
{
MakeVisible(gGuiShelf);
}


(You have to define the gui that you use with all the book buttons on it (in this example gGuiShelf).

And then turn every button invisible when clicking on it:

Code: ags
function book1_OnClick(GUIControl *control, MouseButton button)
{
book1.Visible=false;
}

function book2_OnClick(GUIControl *control, MouseButton button)
{
book2.Visible=false;
}

function book3_OnClick(GUIControl *control, MouseButton button)
{
book3.Visible=false;
}

function book4_OnClick(GUIControl *control, MouseButton button)
{
book4.Visible=false;
}



When the function is run, the module automatically recognizes if the mouse is over an invisible button and if so turns that button visible.
It's very simple.

So now, buttons turn invisible when clicking on them, and back to visible when clicking again on where they were.

As it is, it works for Guis with no off-set. If your overall gui (the gGuiShelf in the example) has an off-set to the left and top you could tell me and I could add that, you would simply then have two function instead of the one (MakeVisible).

I sent the module link to your PM's.

It would be actually possible for you to write the ENTIRE thing in only 2 script lines, and absolutely nothing more, but I can't tell you about it because unfortunately there are people in this forum who would probably insult me if I did, because it wouldn't be the most conformal way.

Anyways, this will make things way easier for you.

I worked on something else and realized I could make this easily work for you, too, so there you go.

TheManInBoots

Quote from: TheManInBoots on Tue 17/03/2020 15:22:59
Yeah, I can imagine it's too much work for what you're trying to do.
Btw. you could trick your way around not being able to click a transparent button, by having one pixel drawn on the original empty sprite (that you use the method Crimson Wizard suggested) with 0.1 opacity/transparency for that one pixel in the image editor you use, and the rest transparent. It's a little bit under the table advice, but in case nothing else works...

Just for correction of what I wrote above:
One can click a button with a completely transparent sprite. As long as one has text written in the button text field, it works. And the text dissappears automatically anyways as soon as one adds a background image to the button.
So I wouldn't advice what I wrote in the quote anymore, and transparent buttons are perfectly possible.

SMF spam blocked by CleanTalk