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 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.toml
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
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
89 changes: 89 additions & 0 deletions crates/bevy_dev_tools/src/fps_overlay.rs
@@ -0,0 +1,89 @@
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;

#[derive(Default)]
/// A plugin that adds an FPS overlay to the Bevy application.
/// Warning: This plugin will add [`FrameTimeDiagnosticsPlugin`] if it wasn't added before.
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Note: It is recommended to use native overlay of the rendering `API` when possible. You can do
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
/// this by:
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
/// - **Metal**: setting env variable `MTL_HUD_ENABLED=1`
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) {
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,
),
);
}
}

#[derive(Resource, Clone)]
/// Configuration options for the FPS overlay.
pub struct FpsOverlayConfig(pub TextStyle);
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved

impl Default for FpsOverlayConfig {
fn default() -> Self {
FpsOverlayConfig(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.0.clone()),
TextSection::from_style(overlay_config.0.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.0.clone();
}
}
}
3 changes: 3 additions & 0 deletions crates/bevy_dev_tools/src/lib.rs
Expand Up @@ -2,8 +2,11 @@
//! focused on improving developer experience.

use bevy_app::prelude::*;

#[cfg(feature = "bevy_ci_testing")]
pub mod ci_testing;
/// Module containing logic for FPS overlay.
matiqo15 marked this conversation as resolved.
Show resolved Hide resolved
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
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
63 changes: 63 additions & 0 deletions examples/dev_tools/fps_overlay.rs
@@ -0,0 +1,63 @@
//! 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(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.0.color = Color::srgb(1.0, 0.0, 0.0);
}
if input.just_pressed(KeyCode::Digit2) {
overlay.0.font_size -= 2.0;
}
}