Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_diagnostic/src/frame_count_diagnostics_plugin.rs
6595 views
1
use bevy_app::prelude::*;
2
use bevy_ecs::prelude::*;
3
4
#[cfg(feature = "serialize")]
5
use serde::{
6
de::{Error, Visitor},
7
Deserialize, Deserializer, Serialize, Serializer,
8
};
9
10
/// Maintains a count of frames rendered since the start of the application.
11
///
12
/// [`FrameCount`] is incremented during [`Last`], providing predictable
13
/// behavior: it will be 0 during the first update, 1 during the next, and so forth.
14
///
15
/// # Overflows
16
///
17
/// [`FrameCount`] will wrap to 0 after exceeding [`u32::MAX`]. Within reasonable
18
/// assumptions, one may exploit wrapping arithmetic to determine the number of frames
19
/// that have elapsed between two observations – see [`u32::wrapping_sub()`].
20
#[derive(Debug, Default, Resource, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
21
pub struct FrameCount(pub u32);
22
23
/// Adds frame counting functionality to Apps.
24
#[derive(Default)]
25
pub struct FrameCountPlugin;
26
27
impl Plugin for FrameCountPlugin {
28
fn build(&self, app: &mut App) {
29
app.init_resource::<FrameCount>();
30
app.add_systems(Last, update_frame_count);
31
}
32
}
33
34
/// A system used to increment [`FrameCount`] with wrapping addition.
35
///
36
/// See [`FrameCount`] for more details.
37
pub fn update_frame_count(mut frame_count: ResMut<FrameCount>) {
38
frame_count.0 = frame_count.0.wrapping_add(1);
39
}
40
41
#[cfg(feature = "serialize")]
42
// Manually implementing serialize/deserialize allows us to use a more compact representation as simple integers
43
impl Serialize for FrameCount {
44
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
45
serializer.serialize_u32(self.0)
46
}
47
}
48
49
#[cfg(feature = "serialize")]
50
impl<'de> Deserialize<'de> for FrameCount {
51
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
52
deserializer.deserialize_u32(FrameVisitor)
53
}
54
}
55
56
#[cfg(feature = "serialize")]
57
struct FrameVisitor;
58
59
#[cfg(feature = "serialize")]
60
impl<'de> Visitor<'de> for FrameVisitor {
61
type Value = FrameCount;
62
63
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
64
formatter.write_str(core::any::type_name::<FrameCount>())
65
}
66
67
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
68
where
69
E: Error,
70
{
71
Ok(FrameCount(v))
72
}
73
}
74
75
#[cfg(test)]
76
mod tests {
77
use super::*;
78
79
#[test]
80
fn frame_counter_update() {
81
let mut app = App::new();
82
app.add_plugins(FrameCountPlugin);
83
app.update();
84
85
let frame_count = app.world().resource::<FrameCount>();
86
assert_eq!(1, frame_count.0);
87
}
88
}
89
90
#[cfg(all(test, feature = "serialize"))]
91
mod serde_tests {
92
use super::*;
93
94
use serde_test::{assert_tokens, Token};
95
96
#[test]
97
fn test_serde_frame_count() {
98
let frame_count = FrameCount(100);
99
assert_tokens(&frame_count, &[Token::U32(100)]);
100
}
101
}
102
103