livesplit_core/rendering/
scene.rs

1use super::{
2    entity::{calculate_hash, Entity},
3    resource::{Handle, SharedOwnership},
4    FillShader,
5};
6use crate::platform::prelude::*;
7
8/// Describes a layer of a [`Scene`] to place an [`Entity`] on.
9#[derive(Copy, Clone, PartialEq, Eq)]
10pub enum Layer {
11    /// The bottom layer is the layer where all the less frequently changing
12    /// [`Entities`](Entity) are being placed on.
13    Bottom,
14    /// The top layer is the layer where all the [`Entities`](Entity) that are
15    /// expected to frequently change are being placed on.
16    Top,
17}
18
19impl Layer {
20    /// Returns the appropriate layer to use depending on whether the [`Entity`]
21    /// to place updates frequently or not.
22    pub const fn from_updates_frequently(updates_frequently: bool) -> Self {
23        match updates_frequently {
24            false => Self::Bottom,
25            true => Self::Top,
26        }
27    }
28}
29
30/// A scene describes all the [`Entities`](Entity) to visualize. It consists of
31/// two [`Layers`](Layer) that are supposed to be composited on top of each
32/// other. The bottom [`Layer`] changes infrequently and doesn't need to be
33/// rerendered for most frames. The top [`Layer`] contains all the per frame
34/// changes and needs to be rerendered for every frame. If however it is empty
35/// and both the bottom layer didn't change, then no new frame needs to be
36/// rendered. While the top [`Layer`] is inherently transparent, the bottom
37/// [`Layer`] has a background that needs to be considered.
38pub struct Scene<P, I, L> {
39    rectangle: Handle<P>,
40    background: Option<FillShader>,
41    bottom_hash: u64,
42    bottom_layer_changed: bool,
43    bottom_layer: Vec<Entity<P, I, L>>,
44    top_layer: Vec<Entity<P, I, L>>,
45}
46
47impl<P: SharedOwnership, I: SharedOwnership, L: SharedOwnership> Scene<P, I, L> {
48    /// Creates a new scene with the rectangle provided to use for placing
49    /// rectangle entities.
50    pub fn new(rectangle: Handle<P>) -> Self {
51        Self {
52            rectangle,
53            background: None,
54            bottom_hash: calculate_hash::<P, I, L>(&None, &[]),
55            bottom_layer_changed: false,
56            bottom_layer: Vec::new(),
57            top_layer: Vec::new(),
58        }
59    }
60
61    /// Get a reference to the bottom [`Layer's`](Layer) background. While the
62    /// top [`Layer`] is inherently transparent, the bottom [`Layer`] has a
63    /// background that needs to be considered.
64    pub const fn background(&self) -> &Option<FillShader> {
65        &self.background
66    }
67
68    /// Check if the scene's bottom [`Layer`] changed. Use this method to check
69    /// if the bottom [`Layer`] needs to be rerendered. If the background of the
70    /// bottom [`Layer`] changes this also returns `true`, so the background
71    /// doesn't need to manually be compared.
72    pub const fn bottom_layer_changed(&self) -> bool {
73        self.bottom_layer_changed
74    }
75
76    /// Get a reference to the scene's bottom [`Layer`]. This [`Layer`] is
77    /// intended to infrequently change, so it doesn't need to be rerendered
78    /// every frame.
79    pub fn bottom_layer(&self) -> &[Entity<P, I, L>] {
80        &self.bottom_layer
81    }
82
83    /// Get a reference to the scene's top [`Layer`].
84    pub fn top_layer(&self) -> &[Entity<P, I, L>] {
85        &self.top_layer
86    }
87
88    /// Get access to the rectangle resource the scene stores.
89    pub fn rectangle(&self) -> Handle<P> {
90        self.rectangle.share()
91    }
92
93    /// Set the bottom [`Layer's`](Layer) background.
94    pub fn set_background(&mut self, background: Option<FillShader>) {
95        self.background = background;
96    }
97
98    /// Get a mutable reference to the scene's bottom [`Layer`].
99    pub fn bottom_layer_mut(&mut self) -> &mut Vec<Entity<P, I, L>> {
100        &mut self.bottom_layer
101    }
102
103    /// Get a mutable reference to the scene's top [`Layer`].
104    pub fn top_layer_mut(&mut self) -> &mut Vec<Entity<P, I, L>> {
105        &mut self.top_layer
106    }
107
108    /// Clears all the [`Layers`](Layer) such that no [`Entities`](Entity) are
109    /// left.
110    pub fn clear(&mut self) {
111        self.bottom_layer.clear();
112        self.top_layer.clear();
113    }
114
115    /// Recalculates the hash of the bottom [`Layer`] and checks if it changed.
116    /// The bottom [`Layer`] is intended to infrequently change, such that it
117    /// doesn't need to be rerendered all the time.
118    pub fn recalculate_if_bottom_layer_changed(&mut self) {
119        let new_hash = calculate_hash(&self.background, &self.bottom_layer);
120        self.bottom_layer_changed = new_hash != self.bottom_hash;
121        self.bottom_hash = new_hash;
122    }
123
124    /// Accesses the [`Layer`] specified mutably.
125    pub fn layer_mut(&mut self, layer: Layer) -> &mut Vec<Entity<P, I, L>> {
126        match layer {
127            Layer::Bottom => &mut self.bottom_layer,
128            Layer::Top => &mut self.top_layer,
129        }
130    }
131}