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}