Simulate GUI mouse click using ProcessClick

Started by Let’s Get Cooking, Sat 19/10/2013 01:23:07

Previous topic - Next topic

Let’s Get Cooking

Hello

I am trying to find a method to allow keyboard control of an inventory window.

I currently have it so pressing Tab opens the inventory window and sets mouse cursor to eModeInteract.  In the repeatedly execute I have a small code to move the mouse cursor to a relative grid position on arrow press, and then the following code to click the button at that position when spacebar is pressed.

Code: AGS
if(IsKeyPressed (eKeySpace) == true){
  ProcessClick (mouse.x, mouse.y, eModeInteract);
}


This doesn't seem do anything.  Does anyone know if ProcessClick be used in this manner, or is there something else wrong?

Thank you!
Play ANOMALY RESOLUTION on itch - a split-screen retro arcade shoot 'em up.

monkey0506

The manual entry for ProcessClick states:

QuoteNOTE: This function ignores all interfaces and acts as though the point is directly visible. In other words, if the co-ordinates you pass happen to lie on a button on an interface, what actually happens will be as if the user clicked behind the interface onto the actual screen.

The interface it's referring to is a graphical user interface (aka, a GUI). The InvWindow (and indeed the InventoryItem itself) are displayed on said GUI, so you can't use ProcessClick for this.

Instead, you'll need to handle it manually:

Code: ags
function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
    if (iat != null) iat.RunInteraction(eModeInteract);
    // else { /* do whatever else for non-inventory items... */ }
  }
}


Note that I used on_key_press instead of repeatedly_execute for this. Moving the cursor in rep_ex by using IsKeyPressed is fine, but you don't want to trigger a dozen interactions, so that's what on_key_press is for instead. GetLocationType will return a type of eLocationNothing for InventoryItems, so you have to use the GetAtScreenXY function directly, which will return null if the cursor (or whatever other coordinates you supply) is not over an InventoryItem.

If you want to handle pressing space while not over an InventoryItem, then just add and use an else clause to your if-statement there. ;)

Let’s Get Cooking

Thanks very much for this, it's just what I needed and has sent me in the right direction for many other things!  For reasons I can't quite pin down right now, RunInteraction(eModeInteract) doesn't actually select the item, but if I assign the item to cEgo that gets around it (fully expect I have chosen the wrong mouse mode!)

Code: AGS
  if (keycode == eKeySpace)
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
    if (iat != null) cEgo.ActiveInventory = iat;
    // else { /* do whatever else for non-inventory items... */ }
  } 


Play ANOMALY RESOLUTION on itch - a split-screen retro arcade shoot 'em up.

Khris

RunInteraction(eModeInteract) will simply trigger the inventory item's "interact with item" event. It has no connection to how the mouse works or what clicks do.
To make an inventory active, you have to do exactly what you did.

Let’s Get Cooking

Play ANOMALY RESOLUTION on itch - a split-screen retro arcade shoot 'em up.

monkey0506

This is one of the cases where the engine doesn't prescribe to any type of default logic and leaves it up to you. There are conceivable cases where you might want to actually allow the player to interact with a particular inventory item, but for other items you might want that same interact cursor to simply set the active item. You had asked about processing a mouse-click, and if ProcessClick didn't simply ignore inventory items this is pretty much what it would do. For every cursor mode except eModeWalkto, all ProcessClick does is check what's under the mouse and then call the equivalent "RunInteraction"-esque method. The logic behind what occurs at that point is still up to you to define in the event handlers.

In this case it is simpler to just set the active inventory directly, assuming that you don't want any separate interaction modes to be processed by this key-press. If you did, you could use InventoryItem.IsInteractionAvailable to check for handled interactions, and fall back on setting the active inventory as the default behavior.

SMF spam blocked by CleanTalk