codecraft 0.1.1

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, an immediate-mode UI, audio and gamepad haptics
Documentation
use bevy_ecs::prelude::*;

use super::color::Color;

/// Marks an entity as an interactive, clickable button.
///
/// Combine with [`super::Position`], [`super::Size`], [`ButtonColors`],
/// [`super::Label`] and [`super::Interaction`] (see [`super::menu::spawn_menu`]).
#[derive(Component)]
pub struct ButtonMarker;

/// The fill color a button entity uses in each interaction state.
#[derive(Component, Clone, Copy, Debug)]
pub struct ButtonColors {
    pub base: Color,
    pub hover: Color,
    pub press: Color,
}

impl ButtonColors {
    /// A close button in a title bar: nothing at rest, so the X reads as part
    /// of the bar, and a warning red under the pointer.
    pub fn close() -> Self {
        Self {
            base: Color::srgba(0.0, 0.0, 0.0, 0.0),
            hover: Color::srgb(0.62, 0.22, 0.22),
            press: Color::srgb(0.45, 0.15, 0.15),
        }
    }

    /// A row in an application menu: nothing at rest, so the panel behind it
    /// is one flat surface rather than a column of tiles, and a highlight
    /// under the pointer to say which row the click will land on.
    pub fn row() -> Self {
        Self {
            base: Color::srgba(0.0, 0.0, 0.0, 0.0),
            hover: Color::srgb(0.24, 0.35, 0.55),
            press: Color::srgb(0.18, 0.27, 0.44),
        }
    }
}

impl Default for ButtonColors {
    fn default() -> Self {
        Self {
            base: Color::srgb(0.20, 0.22, 0.28),
            hover: Color::srgb(0.30, 0.33, 0.42),
            press: Color::srgb(0.14, 0.16, 0.21),
        }
    }
}

impl ButtonColors {
    /// Picks the color for the current interaction state.
    pub fn current(&self, hovered: bool, pressed: bool) -> Color {
        if pressed {
            self.press
        } else if hovered {
            self.hover
        } else {
            self.base
        }
    }
}

/// A boxed, no-argument click callback.
pub type ClickHandler = Box<dyn FnMut() + Send + Sync>;

/// Runs [`update_interaction_system`](super::systems::update_interaction_system)'s
/// `clicked` result through the button's callback, via
/// [`dispatch_clicks_system`](super::systems::dispatch_clicks_system).
#[derive(Component)]
pub struct OnClick(pub ClickHandler);