Skip to main content

concinnity_asset/
fps_counter.rs

1// FpsCounter component schema.
2
3use crate::{AssetId, de_opt_asset_ref};
4
5/// Requests a frames-per-second counter; optionally writes it to a
6/// [TextLabel](#textlabel).
7///
8/// Declaring an `FpsCounter` updates the named [TextLabel](#textlabel) with the
9/// current rate once per second. Omit `label` to suppress on-screen display.
10///
11/// To display an FPS overlay, declare a [Font](#font), a
12/// [TextLabel](#textlabel), and an `FpsCounter` that references the label:
13#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
14#[serde(default)]
15#[derive(Default)]
16pub struct FpsCounter {
17    /// A [TextLabel](#textlabel) to update with the current FPS each second.
18    /// Leave unset to suppress on-screen display.
19    #[serde(deserialize_with = "de_opt_asset_ref")]
20    pub label: Option<AssetId>,
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn an_unset_label_suppresses_the_on_screen_readout() {
29        assert!(FpsCounter::default().label.is_none());
30        assert!(
31            serde_json::from_str::<FpsCounter>(r#"{"label":""}"#)
32                .unwrap()
33                .label
34                .is_none()
35        );
36    }
37
38    #[test]
39    fn a_named_label_parses_and_round_trips_through_postcard() {
40        crate::test_support::install_resolvers();
41        let c: FpsCounter = serde_json::from_str(r#"{"label":"fps_chip"}"#).unwrap();
42        assert_eq!(c.label, Some(AssetId(8)));
43
44        let bytes = postcard::to_allocvec(&c).unwrap();
45        let back: FpsCounter = postcard::from_bytes(&bytes).unwrap();
46        assert_eq!(back.label, Some(AssetId(8)));
47    }
48}