Path: blob/main/crates/bevy_diagnostic/src/frame_count_diagnostics_plugin.rs
6595 views
use bevy_app::prelude::*;1use bevy_ecs::prelude::*;23#[cfg(feature = "serialize")]4use serde::{5de::{Error, Visitor},6Deserialize, Deserializer, Serialize, Serializer,7};89/// Maintains a count of frames rendered since the start of the application.10///11/// [`FrameCount`] is incremented during [`Last`], providing predictable12/// behavior: it will be 0 during the first update, 1 during the next, and so forth.13///14/// # Overflows15///16/// [`FrameCount`] will wrap to 0 after exceeding [`u32::MAX`]. Within reasonable17/// assumptions, one may exploit wrapping arithmetic to determine the number of frames18/// that have elapsed between two observations – see [`u32::wrapping_sub()`].19#[derive(Debug, Default, Resource, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]20pub struct FrameCount(pub u32);2122/// Adds frame counting functionality to Apps.23#[derive(Default)]24pub struct FrameCountPlugin;2526impl Plugin for FrameCountPlugin {27fn build(&self, app: &mut App) {28app.init_resource::<FrameCount>();29app.add_systems(Last, update_frame_count);30}31}3233/// A system used to increment [`FrameCount`] with wrapping addition.34///35/// See [`FrameCount`] for more details.36pub fn update_frame_count(mut frame_count: ResMut<FrameCount>) {37frame_count.0 = frame_count.0.wrapping_add(1);38}3940#[cfg(feature = "serialize")]41// Manually implementing serialize/deserialize allows us to use a more compact representation as simple integers42impl Serialize for FrameCount {43fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {44serializer.serialize_u32(self.0)45}46}4748#[cfg(feature = "serialize")]49impl<'de> Deserialize<'de> for FrameCount {50fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {51deserializer.deserialize_u32(FrameVisitor)52}53}5455#[cfg(feature = "serialize")]56struct FrameVisitor;5758#[cfg(feature = "serialize")]59impl<'de> Visitor<'de> for FrameVisitor {60type Value = FrameCount;6162fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {63formatter.write_str(core::any::type_name::<FrameCount>())64}6566fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>67where68E: Error,69{70Ok(FrameCount(v))71}72}7374#[cfg(test)]75mod tests {76use super::*;7778#[test]79fn frame_counter_update() {80let mut app = App::new();81app.add_plugins(FrameCountPlugin);82app.update();8384let frame_count = app.world().resource::<FrameCount>();85assert_eq!(1, frame_count.0);86}87}8889#[cfg(all(test, feature = "serialize"))]90mod serde_tests {91use super::*;9293use serde_test::{assert_tokens, Token};9495#[test]96fn test_serde_frame_count() {97let frame_count = FrameCount(100);98assert_tokens(&frame_count, &[Token::U32(100)]);99}100}101102103