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.
Layout is controlled using a flexbox-like system.
from pybevy.prelude import *
from pybevy.ui import Node, Text, Button, BackgroundColor, BorderColor, UiRect, AlignItems, JustifyContent, PositionType, Interaction, Val
from pybevy.text import TextFont
# 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 root Node that centers its children.
Inside, we'll create a Button entity. The button itself is a Node, and it has
a Text entity as a child to display its label.
def setup(commands: Commands):
commands.spawn(Camera2d())
commands.spawn(
Node(
width=Val.percent(100),
height=Val.percent(100),
align_items=AlignItems.Center,
justify_content=JustifyContent.Center,
)
).with_children(
lambda parent: parent.spawn(
Button,
Node(
width=Val.px(150),
height=Val.px(65),
border=UiRect.all(Val.px(5)),
justify_content=JustifyContent.Center,
align_items=AlignItems.Center,
),
BorderColor.all(Color.BLACK),
BackgroundColor(NORMAL_BUTTON),
).with_child(
lambda parent: parent.spawn(
Text.new("Button"),
TextFont(font_size=40.0),
)
)
)Button Interaction System
This system queries for all Button entities that have had their Interaction
state changed. Based on the state (Pressed, Hovered, or None), we update
the button's BackgroundColor and its child's Text.
def button_system(
interaction_query: Query[tuple[Interaction, Mut[BackgroundColor], Mut[Children]], Changed[Interaction], With[Button]],
text_query: Query[Mut[Text]],
):
for interaction, color, children in interaction_query:
text = text_query.get_mut(children[0])
if interaction == Interaction.Pressed:
text.sections[0].value = "Press"
color.color = PRESSED_BUTTON
elif interaction == Interaction.Hovered:
text.sections[0].value = "Hover"
color.color = HOVERED_BUTTON
else:
text.sections[0].value = "Button"
color.color = NORMAL_BUTTONRunning 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()