⚠️ Beta State

PyBevy is in an early and experimental stage. The API is incomplete, subject to breaking changes without notice, and you should expect bugs. Many features are still under development.

Basic User Interface

Display text and create a simple, interactive button.

Introduction

User Interface (UI) in pybevy is built using the same ECS principles. UI elements are entities with components like Node, Text, and Button.

from pybevy.prelude import *
 
# Define some colors for our button states
NORMAL_BUTTON = Color.srgb(0.15, 0.15, 0.15)
HOVERED_BUTTON = Color.srgb(0.25, 0.25, 0.25)
PRESSED_BUTTON = Color.srgb(0.35, 0.75, 0.35)

Setup

We'll spawn a Camera2d for the UI and a button entity. The button has a Node for sizing, Text for the label, and BackgroundColor for styling.

Node is created with Node() and properties are set individually — the constructor does not accept keyword arguments.

def setup(commands: Commands):
    commands.spawn(Camera2d())
 
    # Create a button node with size
    btn_node = Node()
    btn_node.width = 200.0
    btn_node.height = 65.0
 
    # Spawn button with text directly on the same entity
    commands.spawn(
        Button(),
        btn_node,
        Text("Button"),
        TextFont(font_size=40.0),
        BackgroundColor(NORMAL_BUTTON),
    )

Button Interaction System

This system queries for Button entities whose Interaction has changed. Based on the state (Pressed, Hovered, or None), we update both the button's BackgroundColor and Text.

def button_system(
    query: Query[tuple[Interaction, Mut[BackgroundColor], Mut[Text]], tuple[Changed[Interaction], With[Button]]],
):
    for interaction, color, text in query:
        if interaction.is_pressed:
            text.content = "Press"
            color.color = PRESSED_BUTTON
        elif interaction.is_hovered:
            text.content = "Hover"
            color.color = HOVERED_BUTTON
        elif interaction.is_none:
            text.content = "Button"
            color.color = NORMAL_BUTTON

Running the App

Run the app to see the button. Hover over it and click it to see the color and text change!

@entrypoint
def main(app: App) -> App:
    return (
        app
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
    )
 
if __name__ == "__main__":
    main().run()