Cursor Changes when Mouseovers a Button

Started by KodiakBehr, Sat 28/07/2012 16:35:22

Previous topic - Next topic

KodiakBehr

I could really use a hand here.

First Question:

GUI is constantly on, has a button that is clicked to load the Sierra-style inventory.
When the mouse is over the button, I want it to become a pointer.  When the mouse leaves the button, I want it to go back to the last cursor icon.

So far, so good.  I wrote this to repeatedly execute:

Code: AGS

GUIControl*gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
if (gc == btnInventory) {mouse.SaveCursorUntilItLeaves();mouse.UseModeGraphic(eModePointer);}


Problem is, when you select the inventory item, thus changing the cursor to reflect that inventory item, and then close the inventory window, it will naturally want to change back to its last cursor instead of holding the cursor of the inventory item.  How do I code my way around this?

And second question:

Is it possible to check for a cursor's graphical property, rather than it's mode?  My game generates an overlay just above the cursor that displays the name of an object on a mouseover, but I find it's a little distracting and gets in the way while dialog is occurring.  I'd like to disable that feature when the wait cursor is displayed, but checking cursor.Mode==eModeWait has no effect, so I'm assuming that the cursor is just using the wait graphic, while retaining the original mode?  Does that make sense?  If so, I can't seem to find any command that checks for a cursor's graphic so I can set this overlay to disable.

Khris

According to the manual, mouse.SaveCursorUntilItLeaves() won't work for buttons, only for hotspots, objects and characters. Also, the command doesn't really do anything here, or at least not what you expect, because you aren't changing mouse.Mode, only the current mode's sprite.

Try this:
Code: ags
// above repeatedly_execute
int old_mode;
bool was_over_button;

// inside rep_ex
  GUIControl*gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  if (gc == btnInventory && !was_over_button) { // mouse just went over the button
    was_over_button = true;
    old_mode = mouse.Mode;
    mouse.Mode = eModePointer;
  }
  if (gc != btnInventory && was_over_button) { // mouse just went away from button
    was_over_button = false;
    if (mouse.Mode != eModeUseinv) mouse.Mode = old_mode;
  }

KodiakBehr

#2
Ah, very clever.  That did the trick.  Thank you!  Downside is that it always goes back to the Interact cursor (the mouse.Mode of the inventory) after leaving the inventory.

I did discover a bug that that I can't seem to consistently recreate whereby the original cursor is retained into the inventory, rather than the pointer.  I guess there's not a lot I can do about that if I can't recreate the problem consistently.

I also added a second, similar question about cursor graphics.  I'd appreciate any guidance you could offer.

Khris

Re your second question:
mouse.GetModeGraphic(mouse.Mode) should return the current sprite.
The reason why your check isn't working is another one though: the cursor is the wait cursor, but while the interface is disabled, rep_ex isn't run.
Move the code to repeatedly_execute_always instead.

Btw, I find it much more convenient to use a GUI for cursor texts.

KodiakBehr

#4
The code is present in rep_exec_always under a specific Floating Hotspot script that Calin was good enough to help with last year.  I just wanted to change the display to null when the wait cursor is showing.  Assuming everything in the else condition is fine, is there an obvious reason why this will not work?  Other conditions when thrown in the place of GetModeGraphic seem to accomplish their effects.

Code: AGS

    if (gInventory.Visible==true){}
    else {
      if (mouse.GetModeGraphic(mouse.Mode)==eModeWait){}
      else {oLabel = Overlay.CreateGraphical(FloatToInt(x, eRoundNearest), FloatToInt(y, eRoundNearest) + Offset, sprite.Graphic,  true);
    }
    }



Khris

#5
Edit: Just saw this: mouse.GetModeGraphic() returns the sprite slot, not the cursor mode.
So it should be if (mouse.GetModeGraphic(mouse.Mode) != 2001) (didn't look up the slot number)
---

I see, you could try IsInterfaceEnabled instead.

Btw, there's no need to use empty {}s and else, you can use ! which will inverse the condition:
Code: ags
  if (!gInventory.Visible && IsInterfaceEnabled()) {
    oLabel = Overlay.CreateGraphical(FloatToInt(x, eRoundNearest), FloatToInt(y, eRoundNearest) + Offset, sprite.Graphic,  true);
  }

Also, it's sorta bad practice to continuously recreate the overlay, but it'll work of course.

KodiakBehr

That's perfect!  Thanks a lot.  I also appreciate the guidance on inversing conditions...that will make life much easier for me :)

KodiakBehr

I hate to re-open this question, but I feel like I'm close to the answer.

Khris' code worked fine if there is a single button that you want to be a pointer only during a mouseover.  But now there is a second button in the GUI for which I want the same effect.  So what I tried was this:

Code: ags

GUIControl*gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  if (gc == btnInventory|| gc == btnControlPanel && !was_over_button) { // mouse just went over the button
    was_over_button = true;
    old_mode = mouse.Mode;
    mouse.Mode = eModePointer;
  }
  

  if (gc != btnInventory&& gc != btnControlPanel && was_over_button) { // mouse just went away from button
    was_over_button = false;
    if (mouse.Mode != eModeUseinv) mouse.Mode = old_mode;
  }


But what ends up happening is the cursor only changes back after mouseovering the control panel, but the Inventory, it stays a pointer.  Do you have any idea why this is and what I can do about it?

Khris

Each button needs their own was_over_button variable.

KodiakBehr

Shoot.  Thanks again, Khris.  I really appreciate it.

SMF spam blocked by CleanTalk