bevy_feathers 0.20.0

A collection of UI widgets for building editors and utilities in Bevy
Documentation
//! `bevy_feathers` is a collection of styled and themed widgets for building editors and
//! inspectors.
//!
//! The aesthetic choices made here are designed with a future Bevy Editor in mind,
//! but this crate is deliberately exposed to the public to allow the broader ecosystem to easily create
//! tooling for themselves and others that fits cohesively together.
//!
//! While it may be tempting to use this crate for your game's UI, it's deliberately not intended for that.
//! We've opted for a clean, functional style, and prioritized consistency over customization.
//! That said, if you like what you see, it can be a helpful learning tool.
//! Consider copying this code into your own project,
//! and refining the styles and abstractions provided to meet your needs.
//!
//! ## Best practices for event propagation
//!
//! Generally, when a widget handles an event,
//! propagation of that event to parent entities should be stopped.
//! This is important when writing your custom widgets, and understanding the behavior of existing widgets.
//!
//! For more guidance on this, see the documentation for [`EntityEvent`](bevy_ecs::event::EntityEvent).

extern crate alloc;

use bevy_app::{
    HierarchyPropagatePlugin, Plugin, PluginGroup, PluginGroupBuilder, PostUpdate, PropagateSet,
};
use bevy_asset::embedded_asset;
use bevy_ecs::{query::With, schedule::IntoScheduleConfigs};
use bevy_input_focus::tab_navigation::TabNavigationPlugin;
use bevy_picking::cursor::{CursorIconPlugin, DefaultCursor, EntityCursor};
use bevy_text::{TextColor, TextFont};
use bevy_ui::{AccessibilityUiSystems, UiSystems};
use bevy_ui_render::{ImageNodeAssetChangedSystems, UiMaterialPlugin};

use crate::{
    alpha_pattern::{AlphaPatternMaterial, AlphaPatternResource},
    controls::ControlsPlugin,
    theme::{ThemeContext, ThemedText, UiTheme},
};

mod alpha_pattern;
pub mod constants;
pub mod containers;
pub mod controls;
pub mod dark_theme;
pub mod display;
pub mod focus;
pub mod font_styles;
pub mod palette;
pub mod rounded_corners;
pub mod theme;
pub mod tokens;

/// Plugin which installs observers and systems for feathers themes, cursors, and all controls.
pub struct FeathersCorePlugin;

impl Plugin for FeathersCorePlugin {
    fn build(&self, app: &mut bevy_app::App) {
        app.init_resource::<UiTheme>();

        // Embedded font
        embedded_asset!(app, "assets/fonts/FiraSans-Bold.ttf");
        embedded_asset!(app, "assets/fonts/FiraSans-BoldItalic.ttf");
        embedded_asset!(app, "assets/fonts/FiraSans-Regular.ttf");
        embedded_asset!(app, "assets/fonts/FiraSans-Italic.ttf");
        embedded_asset!(app, "assets/fonts/FiraMono-Medium.ttf");
        embedded_asset!(app, "assets/fonts/NotoSansSymbols2-U+1F7D5.ttf");

        // Embedded icons
        embedded_asset!(app, "assets/icons/chevron-down.png");
        embedded_asset!(app, "assets/icons/chevron-right.png");
        embedded_asset!(app, "assets/icons/x.png");

        // Embedded shader
        embedded_asset!(app, "assets/shaders/alpha_pattern.wesl");
        embedded_asset!(app, "assets/shaders/color_plane.wesl");
        embedded_asset!(app, "assets/shaders/color_wheel.wesl");

        app.add_plugins((
            ControlsPlugin,
            CursorIconPlugin,
            HierarchyPropagatePlugin::<TextColor, With<ThemedText>>::new(PostUpdate),
            HierarchyPropagatePlugin::<TextFont, With<ThemedText>>::new(PostUpdate),
            HierarchyPropagatePlugin::<ThemeContext>::new(PostUpdate),
            UiMaterialPlugin::<AlphaPatternMaterial>::default(),
            focus::FocusOutlinesPlugin,
        ));

        // This needs to run in UiSystems::Propagate so the fonts are up-to-date for `measure_text_system`
        // and `detect_text_needs_rerender` in UiSystems::Content
        app.configure_sets(
            PostUpdate,
            PropagateSet::<TextFont>::default().in_set(UiSystems::Propagate),
        );
        app.configure_sets(
            PostUpdate,
            PropagateSet::<TextColor>::default().in_set(UiSystems::Propagate),
        );

        app.insert_resource(DefaultCursor(EntityCursor::System(
            bevy_window::SystemCursorIcon::Default,
        )));

        app.add_systems(
            PostUpdate,
            (
                theme::update_theme.in_set(UiSystems::Prepare),
                display::update_themed_icons
                    .after(PropagateSet::<TextColor>::default())
                    // These systems deal with the underlying asset of the ImageNode,
                    // which this system does not change.
                    .ambiguous_with(ImageNodeAssetChangedSystems)
                    // These systems merely update the `AccessibilityNode` and do not depend
                    // on any changes `update_themed_icons` does to an image node.
                    .ambiguous_with(AccessibilityUiSystems)
                    // `update_themed_icons` does not affect the size of content.
                    .ambiguous_with(UiSystems::Content),
            )
                .chain(),
        )
        .add_observer(theme::on_changed_background)
        .add_observer(theme::on_changed_border)
        .add_observer(theme::on_changed_font_color)
        .add_observer(theme::on_changed_text_color)
        .add_observer(font_styles::on_changed_font);

        app.init_resource::<AlphaPatternResource>();
    }
}

/// A plugin group that adds all dependencies for Feathers
pub struct FeathersPlugins;

impl PluginGroup for FeathersPlugins {
    fn build(self) -> PluginGroupBuilder {
        PluginGroupBuilder::start::<Self>()
            .add(TabNavigationPlugin)
            .add(FeathersCorePlugin)
    }
}