MinecraftButton

A pixel stone menu button that cracks every few taps, shatters into chips, and drops itself as a bobbing item you pick up to respawn it.

Preview

Loading GPUI

Props

Install

cargo add evilbuttons

The label wants a pixel font. The demos use Pixelify Sans (SIL Open Font License); load it into GPUI and pass its family name:

cx.text_system().add_fonts(vec![
    std::borrow::Cow::Borrowed(include_bytes!("../assets/fonts/PixelifySans.ttf").as_slice()),
])?;

Usage

use evilbuttons::MinecraftButton;
use gpui::{div, prelude::*, Context, IntoElement, Render, Window};

struct ButtonDemo;

impl Render for ButtonDemo {
    fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
        div().child(
            MinecraftButton::new("singleplayer")
                .font_family("Pixelify Sans")
                .taps_per_stage(5)
                .stages(4)
                .on_crack(|stage, _, _| println!("Crack stage {stage}"))
                .on_break(|_, _| println!("Broken.")),
        )
    }
}

Props

MinecraftButton is a GPUI RenderOnce builder; its taps, cracks and dropped item are keyed by id.

MethodTypeDefaultDescription
new(id)impl Into<ElementId>-Unique id for the button state.
label(s)impl Into<SharedString>"Singleplayer"Button label.
taps_per_stage(n)u325Taps needed to advance one crack stage.
stages(n)u324Stages until it breaks. The button breaks after taps_per_stage * stages taps.
pickaxe(bool)booltrueDraw a pixel pickaxe at the pointer that winds up on press and strikes on release.
respawn_after(d)Duration-Respawn automatically after this long. Unset, it waits for the drop to be picked up.
font_family(f)impl Into<SharedString>inheritedFont for the label and the item tooltip, e.g. a pixel font.
on_click(f)Fn(&ClickEvent, &mut Window, &mut App)-Fired on every tap, before it counts.
on_crack(f)Fn(u32, &mut Window, &mut App)-Fired when the crack deepens to a new stage.
on_break(f)Fn(&mut Window, &mut App)-Fired when the button breaks.
on_respawn(f)Fn(&mut Window, &mut App)-Fired when the button comes back.
disabled(bool)boolfalseDarkens the stone and ignores input.

Good to know

  • Everything snaps to a 3px texel grid, and the stone texture and crack pattern are seeded, so they match the React version pixel for pixel.
  • GPUI can't hide the system cursor, so the pickaxe is drawn next to a crosshair cursor whose centre sits on the pickaxe's tip.
  • There are no sounds: GPUI has no audio API, so the React version's sound prop has no equivalent here.

Search docs

Jump to a button documentation page