Interaction and Widget Callbacks
What use is a UI system if you cannot interact with it? gooey is a mouse-based UI library, so it is designed to respond to different mouse events. In this page, we will see how to set them up.
Additionally, we will see special interactions that we can setup to perform tasks either before or after the widget is rendered. These will prove very useful for updating widget properties and make them keep up with what's happening on the game.
The UI events
gooey has different UI events built in that you can use to set up interactions with. These are grouped in the UI_EVENT enum. This enum has the following values:
| Event | When does it fire? |
|---|---|
MOUSE_OVER |
When the mouse is over the widget |
LEFT_CLICK |
When the left mouse button is clicked over the widget |
MIDDLE_CLICK |
When the middle mouse button is clicked over the widget |
RIGHT_CLICK |
When the right mouse button is clicked over the widget |
LEFT_HOLD |
When the left mouse button is held over the widget |
MIDDLE_HOLD |
When the middle mouse button is held over the widget |
RIGHT_HOLD |
When the rightg mouse button is held over the widget |
LEFT_RELEASE |
When the left mouse button is released over the widget |
MIDDLE_RELEASE |
When the middle mouse button is released over the widget |
RIGHT_RELEASE |
When the right mouse button is released over the widget |
MOUSE_ENTER |
When the mouse enters the widget (compared to the last frame) |
MOUSE_EXIT |
When the mouse exits the widget (compared to the last frame) |
MOUSE_WHEEL_UP |
When the mouse wheel is scrolled up over the widget |
MOUSE_WHEEL_DOWN |
When the mouse wheel is scrolled down over the widget |
Additionally, it's worth noting that there's another value in the enum that, while it doesn't correspond to a mouse interaction, it can still be detected and can determine behavior:
| Event | When does it fire? |
|---|---|
VALUE_CHANGED |
When the value of the widget changed (compared to the last frame) |
You can define behavior for any of these, for any of your widgets.
Double click
The double click event is not supported in gooey.
Touch interaction
Touch interactions are supported in gooey in the sense that event checks are internally coded using the device_mouse_...(device) GameMaker functions. The device ID is set to 0 by default, but you can change this with the ui_set_mouse_device() convenience function, if you need.
UIText
Prior to gooey 2025.4, UIText elements do not support events.
LEFT_RELEASE not supported for Panels
The LEFT_RELEASE event is currently not supported for UIPanel widgets because it interferes with the dragging action.
Callbacks
For the purposes of gooey, a callback is a function that gets called when a UI event for a widget occurs. The callback function has the logic that is processed when the corresponding UI event is fired, so they are used to define the behavior of the UI.
To set up a callback, we can use the .setCallback() method:
Method signature
The first parameter must be a member of the UI_EVENT enum, as described above; and the second parameter is the function to call when the event happens.
For example, let's create a button inside a panel, and assign behavior to it by setting a callback when the user releases the mouse button:
This yields the following:
In the example code above you see the highlighted lines where we are configuring the behavior. First, we are using LEFT_RELEASE as the enum value, to tell gooey we want to fire off a behavior when the player releases the left mouse button. Then, we are specifying an anonymous function which gets the panel by name and then calls the .setSprite() method to configure its sprite.
Context of self
When specifying callbacks, you will not be able to natively use self for refering to the calling widget, unless you explicitly bind the callback to the widget using method().
For example, in the code above, suppose instead of changing the color of the panel, you wanted to change the color of the button itself. You would not be able to define the callback directly like so:
// This will not work
_button.setCallback(UI_EVENT.LEFT_RELEASE, function() {
self.setSprite(choose(blue_button00, green_button00, red_button00, grey_button00, yellow_button00));
});
Instead, you would need to bind it first using method() like so:
// This will work
_button.setCallback(UI_EVENT.LEFT_RELEASE, method(_button, function() {
self.setSprite(choose(blue_button00, green_button00, red_button00, grey_button00, yellow_button00));
}));
If you need to better understand why this behaves like it does, you can check the GameMaker's documentation on method().
Note that, with the exception of things like spinner buttons, tab buttons or the automatic close button, in general gooey widgets do not have any kind of predefined callbacks. You must define your own callbacks to tell the system what to do.
Callback drill-through
gooey UI events work on the top-most widget being hovered. This means if you had a button over a group over a panel, the behaviors executed for each event fired will correspond to those defined on the button. If that element does not have a callback defined for the fired event, by default gooey will not process any other callbacks.
However, you can activate a drill-through mechanism whereby, if the widget does not have a callback for the specified event, gooey will go to its parent instead, and will keep doing this recursively until either a defined callback exists or no parent exists. By using the drill-through mechanism, you can avoid some inconvenient behavior.
For example, in a similar example as above, let's say that we want to add a sprite to the button. We have defined our callback as before, and now we've added a sprite as a child to the button:
Now, if we click on the button, it works as before... except if we click when hovering over the sprite! This is not what we want. We could fix this by setting the callback of the sprite as well, so it does the same thing as the button callback... but this is not efficient. We can instead fix this though by enabling drill-through for the LEFT_RELEASE event of the sprite like so:
You can test the behavior of the drill-through with the following interactive example. By clicking on the toggle, you can enable or disable drill-through for LEFT_RELEASE for the heart sprite. Try clicking over the heart sprite with drill-through enabled or disabled to see the difference.
Enabling/disabling drill-through
You can enable or disable drill-through for a specific event; also you can enable it globaly for all widgets (on the Configuration script) or per widget, by using the .setDrillThrough...() setters.
Wrapping up
The mouse event system of gooey provides flexibility for defining and configuring your UI interaction, creating intuitive interfaces.