bevy_webcam 0.4.0

bevy webcam plugin
Documentation
use bevy::{
    prelude::*,
    app::AppExit,
    color::palettes::css::GOLD,
    diagnostic::{
        DiagnosticsStore,
        FrameTimeDiagnosticsPlugin,
    },
};

use bevy_webcam::{
    BevyWebcamPlugin,
    WebcamStream,
};


fn main() {
    let mut app = App::new();

    app.add_plugins((
        DefaultPlugins
            .set(WindowPlugin {
                primary_window: Window {
                    title: "bevy_webcam".to_string(),
                    fit_canvas_to_parent: true,
                    ..default()
                }.into(),
                ..default()
            }),
        BevyWebcamPlugin::default(),
    ));

    app.add_systems(Startup, setup_ui);

    app.add_systems(Update, press_esc_close);

    app.add_plugins(FrameTimeDiagnosticsPlugin::default());
    app.add_systems(Startup, fps_display_setup);
    app.add_systems(Update, fps_update_system);

    app.run();
}


fn setup_ui(
    mut commands: Commands,
    stream: Res<WebcamStream>,
) {
    commands.spawn(Camera2d);

    commands.spawn((
        ImageNode {
            image: stream.frame.clone(),
            ..default()
        },
        Node {
            width: Val::Percent(100.0),
            height: Val::Percent(100.0),
            ..default()
        },
    ));
}


pub fn press_esc_close(
    keys: Res<ButtonInput<KeyCode>>,
    mut exit: MessageWriter<AppExit>
) {
    if keys.just_pressed(KeyCode::Escape) {
        exit.write(AppExit::Success);
    }
}


fn fps_display_setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    commands.spawn((
        Text("fps: ".to_string()),
        TextFont {
            font: asset_server.load("fonts/Caveat-Bold.ttf"),
            font_size: 60.0,
            ..Default::default()
        },
        TextColor(Color::WHITE),
        Node {
            position_type: PositionType::Absolute,
            bottom: Val::Px(5.0),
            left: Val::Px(15.0),
            ..default()
        },
        ZIndex(2),
    )).with_child((
        FpsText,
        TextColor(Color::Srgba(GOLD)),
        TextFont {
            font: asset_server.load("fonts/Caveat-Bold.ttf"),
            font_size: 60.0,
            ..Default::default()
        },
        TextSpan::default(),
    ));
}

#[derive(Component)]
struct FpsText;

fn fps_update_system(
    diagnostics: Res<DiagnosticsStore>,
    mut query: Query<&mut TextSpan, With<FpsText>>,
) {
    for mut text in &mut query {
        if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS)
            && let Some(value) = fps.smoothed()
        {
            **text = format!("{value:.2}");
        }
    }
}