1use crate::{
2 color::ColorU,
3 fonts::{FontId, GlyphId},
4 geometry::{rect::RectF, vector::Vector2F},
5};
6
7pub struct Scene {
8 scale_factor: f32,
9 layers: Vec<Layer>,
10 active_layer_stack: Vec<usize>,
11}
12
13#[derive(Default, Debug)]
14pub struct Layer {
15 clip_bounds: Option<RectF>,
16 quads: Vec<Quad>,
17 shadows: Vec<Shadow>,
18 glyphs: Vec<Glyph>,
19}
20
21#[derive(Default, Debug)]
22pub struct Quad {
23 pub bounds: RectF,
24 pub background: Option<ColorU>,
25 pub border: Border,
26 pub corner_radius: f32,
27}
28
29#[derive(Debug)]
30pub struct Shadow {
31 pub bounds: RectF,
32 pub corner_radius: f32,
33 pub sigma: f32,
34 pub color: ColorU,
35}
36
37#[derive(Debug)]
38pub struct Glyph {
39 pub font_id: FontId,
40 pub font_size: f32,
41 pub id: GlyphId,
42 pub origin: Vector2F,
43 pub color: ColorU,
44}
45
46#[derive(Clone, Copy, Default, Debug)]
47pub struct Border {
48 pub width: f32,
49 pub color: Option<ColorU>,
50 pub top: bool,
51 pub right: bool,
52 pub bottom: bool,
53 pub left: bool,
54}
55
56impl Scene {
57 pub fn new(scale_factor: f32) -> Self {
58 Scene {
59 scale_factor,
60 layers: vec![Layer::default()],
61 active_layer_stack: vec![0],
62 }
63 }
64
65 pub fn scale_factor(&self) -> f32 {
66 self.scale_factor
67 }
68
69 pub fn layers(&self) -> &[Layer] {
70 self.layers.as_slice()
71 }
72
73 pub fn push_layer(&mut self) {
74 let ix = self.layers.len();
75 self.layers.push(Layer::default());
76 self.active_layer_stack.push(ix);
77 }
78
79 pub fn pop_layer(&mut self) {
80 assert!(self.active_layer_stack.len() > 1);
81 self.active_layer_stack.pop();
82 }
83
84 pub fn push_quad(&mut self, quad: Quad) {
85 self.active_layer().push_quad(quad)
86 }
87
88 pub fn push_shadow(&mut self, shadow: Shadow) {
89 self.active_layer().push_shadow(shadow)
90 }
91
92 pub fn push_glyph(&mut self, glyph: Glyph) {
93 self.active_layer().push_glyph(glyph)
94 }
95
96 fn active_layer(&mut self) -> &mut Layer {
97 &mut self.layers[*self.active_layer_stack.last().unwrap()]
98 }
99}
100
101impl Layer {
102 fn push_quad(&mut self, quad: Quad) {
103 self.quads.push(quad);
104 }
105
106 pub fn quads(&self) -> &[Quad] {
107 self.quads.as_slice()
108 }
109
110 fn push_shadow(&mut self, shadow: Shadow) {
111 self.shadows.push(shadow);
112 }
113
114 pub fn shadows(&self) -> &[Shadow] {
115 self.shadows.as_slice()
116 }
117
118 fn push_glyph(&mut self, glyph: Glyph) {
119 self.glyphs.push(glyph);
120 }
121
122 pub fn glyphs(&self) -> &[Glyph] {
123 self.glyphs.as_slice()
124 }
125}
126
127impl Border {
128 pub fn new(width: f32, color: impl Into<ColorU>) -> Self {
129 Self {
130 width,
131 color: Some(color.into()),
132 top: false,
133 left: false,
134 bottom: false,
135 right: false,
136 }
137 }
138
139 pub fn all(width: f32, color: impl Into<ColorU>) -> Self {
140 Self {
141 width,
142 color: Some(color.into()),
143 top: true,
144 left: true,
145 bottom: true,
146 right: true,
147 }
148 }
149
150 pub fn top(width: f32, color: impl Into<ColorU>) -> Self {
151 let mut border = Self::new(width, color);
152 border.top = true;
153 border
154 }
155
156 pub fn left(width: f32, color: impl Into<ColorU>) -> Self {
157 let mut border = Self::new(width, color);
158 border.left = true;
159 border
160 }
161
162 pub fn bottom(width: f32, color: impl Into<ColorU>) -> Self {
163 let mut border = Self::new(width, color);
164 border.bottom = true;
165 border
166 }
167
168 pub fn right(width: f32, color: impl Into<ColorU>) -> Self {
169 let mut border = Self::new(width, color);
170 border.right = true;
171 border
172 }
173
174 pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
175 self.top = top;
176 self.left = left;
177 self.bottom = bottom;
178 self.right = right;
179 self
180 }
181
182 fn all_sides(&self) -> bool {
183 self.top && self.left && self.bottom && self.right
184 }
185}