Button

Namespace:

namespace Lenga\Engine\UI;

final class Button extends UIElement

A clickable UI element. Button extends UIElement and adds text, colour, optional state images, and interaction-state properties. Obtain a reference via Canvas::getElement() or by looking up the element name on a Canvas component.

Interaction state properties

These read-only properties expose the button's current interaction state. Query them inside update().

Property Type Description
$hovered bool true every frame the cursor is over the button.
$pressed bool true every frame the mouse button is held down while the cursor is over the button. Use with care — this fires continuously for every frame the button is held.
$pressedThisFrame bool true only on the first frame the mouse button goes down over the button (edge-triggered).
$releasedThisFrame bool true only on the first frame the mouse button is released over the button (edge-triggered).
$clicked bool true only on the first frame after a full press-and-release cycle completes while the cursor is over the button. Prefer this for menu actions and one-shot triggers.

Tip — Use $clicked for most menu interactions. It fires exactly once per click, equivalent to a traditional button click event. Use $pressed only when you genuinely need continuous feedback (e.g., a hold-to-charge mechanic).

Appearance properties

Property Type Description
$text string The label displayed on the button. Readable and writable.
$fontSize float Font size in points. Readable and writable. Default 24.0.
$fontPath string Path to a custom font file. Readable and writable.
$interactable bool When false, the button is displayed with its disabled colour and ignores all input. Readable and writable.

State image methods

Each button state can use a texture image instead of relying only on colour. Paths are project-relative asset paths such as Assets/Sprites/UI/ButtonIdle.png.

Method Description
setBackgroundImage(path) / getBackgroundImage() Default image used when the button is idle.
setHoverImage(path) / getHoverImage() Image used while the cursor is over the button. If empty, the button falls back to the default image or hover colour.
setPressedImage(path) / getPressedImage() Image used while the mouse button is held down over the button. If empty, the button falls back to the default image or pressed colour.
setDisabledImage(path) / getDisabledImage() Image used when $interactable is false. If empty, the button falls back to the default image or disabled colour.

If a state image is assigned, that image represents the state directly. If a state image is not assigned but the default image is assigned, Lenga uses the default image and applies the state colour as feedback. If no image is available, Lenga draws the button with the state colour.

Colour methods

Each colour is returned as an array{r:int, g:int, b:int, a:int} and changed via the corresponding setter.

Method Description
getTextColor() / setTextColor(r, g, b, a) Foreground (label) colour. Default: white.
getBackgroundColor() / setBackgroundColor(r, g, b, a) Normal state background.
getHoverColor() / setHoverColor(r, g, b, a) Background while the cursor is over the button.
getPressedColor() / setPressedColor(r, g, b, a) Background while the mouse button is held down.
getDisabledColor() / setDisabledColor(r, g, b, a) Background when $interactable is false.

Example

use Lenga\Engine\Core\Behaviour;
use Lenga\Engine\UI\Button;
use Lenga\Engine\UI\Canvas;
use Lenga\Engine\SceneManagement\SceneManager;

class MainMenu extends Behaviour
{
    private ?Button $playButton = null;
    private ?Button $quitButton = null;

    public function start(): void
    {
        $canvas = $this->getComponent(Canvas::class);

        $this->playButton = $canvas->getElement('PlayButton');
        $this->quitButton = $canvas->getElement('QuitButton');

        // Style the play button
        $this->playButton->setBackgroundColor(34, 139, 34, 255);
        $this->playButton->setHoverColor(50, 180, 50, 255);
        $this->playButton->setBackgroundImage('Assets/Sprites/UI/PlayButton.png');
        $this->playButton->setHoverImage('Assets/Sprites/UI/PlayButtonHover.png');
        $this->playButton->setPressedImage('Assets/Sprites/UI/PlayButtonPressed.png');
    }

    public function update(): void
    {
        // clicked fires exactly once per full press-and-release cycle
        if ($this->playButton?->clicked) {
            SceneManager::loadScene('Game');
        }

        if ($this->quitButton?->clicked) {
            Application::quit();
        }
    }
}