Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fps overlay #12382

Merged
merged 21 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2763,6 +2763,18 @@ description = "A scene showcasing light gizmos"
category = "Gizmos"
wasm = true

[[example]]
name = "fps_overlay"
path = "examples/dev_tools/fps_overlay.rs"
doc-scrape-examples = true
required-features = ["bevy_dev_tools"]

[package.metadata.example.fps_overlay]
name = "FPS overlay"
description = "Demonstrates FPS overlay"
category = "Dev tools"
wasm = true

[profile.wasm-release]
inherits = "release"
opt-level = "z"
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_dev_tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" }
bevy_render = { path = "../bevy_render", version = "0.14.0-dev" }
bevy_time = { path = "../bevy_time", version = "0.14.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.14.0-dev" }
bevy_asset = { path = "../bevy_asset", version = "0.14.0-dev" }
bevy_ui = { path = "../bevy_ui", version = "0.14.0-dev" }
bevy_text = { path = "../bevy_text", version = "0.14.0-dev" }
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.14.0-dev" }
bevy_color = { path = "../bevy_color", version = "0.14.0-dev" }
bevy_input = { path = "../bevy_input", version = "0.14.0-dev" }

# other
serde = { version = "1.0", features = ["derive"], optional = true }
Expand Down
98 changes: 98 additions & 0 deletions crates/bevy_dev_tools/src/fps_overlay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//! Module containing logic for FPS overlay.

use bevy_app::{Plugin, Startup, Update};
use bevy_asset::Handle;
use bevy_color::Color;
use bevy_diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
use bevy_ecs::{
component::Component,
query::With,
schedule::{common_conditions::resource_changed, IntoSystemConfigs},
system::{Commands, Query, Res, Resource},
};
use bevy_text::{Font, Text, TextSection, TextStyle};
use bevy_ui::node_bundles::TextBundle;

/// A plugin that adds an FPS overlay to the Bevy application.
///
/// This plugin will add the [`FrameTimeDiagnosticsPlugin`] if it wasn't added before.
///
/// Note: It is recommended to use native overlay of rendering statistics when possible for lower overhead and more accurate results.
/// The correct way to do this will vary by platform:
/// - **Metal**: setting env variable `MTL_HUD_ENABLED=1`
#[derive(Default)]
pub struct FpsOverlayPlugin {
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
/// Starting configuration of overlay, this can be later be changed through [`FpsOverlayConfig`] resource.
pub config: FpsOverlayConfig,
}

impl Plugin for FpsOverlayPlugin {
fn build(&self, app: &mut bevy_app::App) {
// TODO: Use plugin dependencies, see https://github.com/bevyengine/bevy/issues/69
if !app.is_plugin_added::<FrameTimeDiagnosticsPlugin>() {
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
app.add_plugins(FrameTimeDiagnosticsPlugin);
}
app.insert_resource(self.config.clone())
.add_systems(Startup, setup)
.add_systems(
Update,
(
customize_text.run_if(resource_changed::<FpsOverlayConfig>),
update_text,
),
);
}
}

/// Configuration options for the FPS overlay.
#[derive(Resource, Clone)]
pub struct FpsOverlayConfig {
/// Configuration of text in the overlay.
pub text_config: TextStyle,
}

impl Default for FpsOverlayConfig {
fn default() -> Self {
FpsOverlayConfig {
text_config: TextStyle {
font: Handle::<Font>::default(),
font_size: 32.0,
color: Color::WHITE,
},
}
}
}

#[derive(Component)]
struct FpsText;

fn setup(mut commands: Commands, overlay_config: Res<FpsOverlayConfig>) {
commands.spawn((
TextBundle::from_sections([
TextSection::new("FPS: ", overlay_config.text_config.clone()),
TextSection::from_style(overlay_config.text_config.clone()),
]),
FpsText,
));
}

fn update_text(diagnostic: Res<DiagnosticsStore>, mut query: Query<&mut Text, With<FpsText>>) {
for mut text in &mut query {
if let Some(fps) = diagnostic.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(value) = fps.smoothed() {
text.sections[1].value = format!("{value:.2}");
}
}
}
}

fn customize_text(
overlay_config: Res<FpsOverlayConfig>,
mut query: Query<&mut Text, With<FpsText>>,
) {
for mut text in &mut query {
for section in text.sections.iter_mut() {
section.style = overlay_config.text_config.clone();
}
}
}
2 changes: 2 additions & 0 deletions crates/bevy_dev_tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
//! focused on improving developer experience.

use bevy_app::prelude::*;

#[cfg(feature = "bevy_ci_testing")]
pub mod ci_testing;
pub mod fps_overlay;

/// Enables developer tools in an [`App`]. This plugin is added automatically with `bevy_dev_tools`
/// feature.
Expand Down
7 changes: 7 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ git checkout v0.4.0
- [Assets](#assets)
- [Async Tasks](#async-tasks)
- [Audio](#audio)
- [Dev tools](#dev-tools)
- [Diagnostics](#diagnostics)
- [ECS (Entity Component System)](#ecs-entity-component-system)
- [Games](#games)
Expand Down Expand Up @@ -219,6 +220,12 @@ Example | Description
[Spatial Audio 2D](../examples/audio/spatial_audio_2d.rs) | Shows how to play spatial audio, and moving the emitter in 2D
[Spatial Audio 3D](../examples/audio/spatial_audio_3d.rs) | Shows how to play spatial audio, and moving the emitter in 3D

## Dev tools

Example | Description
--- | ---
[FPS overlay](../examples/dev_tools/fps_overlay.rs) | Demonstrates FPS overlay

## Diagnostics

Example | Description
Expand Down
65 changes: 65 additions & 0 deletions examples/dev_tools/fps_overlay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! Showcase how to use and configure FPS overlay.

use bevy::{
dev_tools::fps_overlay::{FpsOverlayConfig, FpsOverlayPlugin},
prelude::*,
};

fn main() {
App::new()
.add_plugins((
DefaultPlugins,
FpsOverlayPlugin {
config: FpsOverlayConfig {
text_config: TextStyle {
// Here we define size of our overlay
font_size: 50.0,
// We can also change color of the overlay
color: Color::srgb(0.0, 1.0, 0.0),
// If we want, we can use a custom font
font: default(),
},
},
},
))
.add_systems(Startup, setup)
.add_systems(Update, customize_config)
.run();
}

fn setup(mut commands: Commands) {
// We need to spawn camera to see overlay
commands.spawn(Camera2dBundle::default());
commands.spawn(
TextBundle::from_sections([
TextSection::new(
"Press 1 to change color of the overlay.",
TextStyle {
font_size: 25.0,
..default()
},
),
TextSection::new(
"\nPress 2 to change size of the overlay",
TextStyle {
font_size: 25.0,
..default()
},
),
])
.with_style(Style {
justify_self: JustifySelf::Center,
..default()
}),
);
}

fn customize_config(input: Res<ButtonInput<KeyCode>>, mut overlay: ResMut<FpsOverlayConfig>) {
if input.just_pressed(KeyCode::Digit1) {
// Changing resource will affect overlay
overlay.text_config.color = Color::srgb(1.0, 0.0, 0.0);
}
if input.just_pressed(KeyCode::Digit2) {
overlay.text_config.font_size -= 2.0;
}
}