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