1use crate::{ahash, epaint, Id, IdMap, Rect};
5use epaint::{emath::TSTransform, ClippedShape, Shape};
6
7#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub enum Order {
11 Background,
13
14 Middle,
16
17 Foreground,
20
21 Tooltip,
24
25 Debug,
27}
28
29impl Order {
30 const COUNT: usize = 5;
31 const ALL: [Self; Self::COUNT] = [
32 Self::Background,
33 Self::Middle,
34 Self::Foreground,
35 Self::Tooltip,
36 Self::Debug,
37 ];
38 pub const TOP: Self = Self::Debug;
39
40 #[inline(always)]
41 pub fn allow_interaction(&self) -> bool {
42 match self {
43 Self::Background | Self::Middle | Self::Foreground | Self::Tooltip | Self::Debug => {
44 true
45 }
46 }
47 }
48
49 pub fn short_debug_format(&self) -> &'static str {
51 match self {
52 Self::Background => "backg",
53 Self::Middle => "middl",
54 Self::Foreground => "foreg",
55 Self::Tooltip => "toolt",
56 Self::Debug => "debug",
57 }
58 }
59}
60
61#[derive(Clone, Copy, Hash, Eq, PartialEq)]
64#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
65pub struct LayerId {
66 pub order: Order,
67 pub id: Id,
68}
69
70impl LayerId {
71 pub fn new(order: Order, id: Id) -> Self {
72 Self { order, id }
73 }
74
75 pub fn debug() -> Self {
76 Self {
77 order: Order::Debug,
78 id: Id::new("debug"),
79 }
80 }
81
82 pub fn background() -> Self {
83 Self {
84 order: Order::Background,
85 id: Id::new("background"),
86 }
87 }
88
89 #[inline(always)]
90 #[deprecated = "Use `Memory::allows_interaction` instead"]
91 pub fn allow_interaction(&self) -> bool {
92 self.order.allow_interaction()
93 }
94
95 pub fn short_debug_format(&self) -> String {
97 format!(
98 "{} {}",
99 self.order.short_debug_format(),
100 self.id.short_debug_format()
101 )
102 }
103}
104
105impl std::fmt::Debug for LayerId {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 let Self { order, id } = self;
108 write!(f, "LayerId {{ {order:?} {id:?} }}")
109 }
110}
111
112#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub struct ShapeIdx(pub usize);
116
117#[derive(Clone, Default)]
119pub struct PaintList(Vec<ClippedShape>);
120
121impl PaintList {
122 #[inline(always)]
123 pub fn is_empty(&self) -> bool {
124 self.0.is_empty()
125 }
126
127 pub fn next_idx(&self) -> ShapeIdx {
128 ShapeIdx(self.0.len())
129 }
130
131 #[inline(always)]
133 pub fn add(&mut self, clip_rect: Rect, shape: Shape) -> ShapeIdx {
134 let idx = self.next_idx();
135 self.0.push(ClippedShape { clip_rect, shape });
136 idx
137 }
138
139 pub fn extend<I: IntoIterator<Item = Shape>>(&mut self, clip_rect: Rect, shapes: I) {
140 self.0.extend(
141 shapes
142 .into_iter()
143 .map(|shape| ClippedShape { clip_rect, shape }),
144 );
145 }
146
147 #[inline(always)]
155 pub fn set(&mut self, idx: ShapeIdx, clip_rect: Rect, shape: Shape) {
156 if self.0.len() <= idx.0 {
157 #[cfg(feature = "log")]
158 log::warn!("Index {} is out of bounds for PaintList", idx.0);
159 return;
160 }
161
162 self.0[idx.0] = ClippedShape { clip_rect, shape };
163 }
164
165 #[inline(always)]
167 pub fn reset_shape(&mut self, idx: ShapeIdx) {
168 self.0[idx.0].shape = Shape::Noop;
169 }
170
171 pub fn mutate_shape(&mut self, idx: ShapeIdx, f: impl FnOnce(&mut ClippedShape)) {
173 self.0.get_mut(idx.0).map(f);
174 }
175
176 pub fn transform(&mut self, transform: TSTransform) {
178 for ClippedShape { clip_rect, shape } in &mut self.0 {
179 *clip_rect = transform.mul_rect(*clip_rect);
180 shape.transform(transform);
181 }
182 }
183
184 pub fn transform_range(&mut self, start: ShapeIdx, end: ShapeIdx, transform: TSTransform) {
186 for ClippedShape { clip_rect, shape } in &mut self.0[start.0..end.0] {
187 *clip_rect = transform.mul_rect(*clip_rect);
188 shape.transform(transform);
189 }
190 }
191
192 pub fn all_entries(&self) -> impl ExactSizeIterator<Item = &ClippedShape> {
194 self.0.iter()
195 }
196}
197
198#[derive(Clone, Default)]
200pub struct GraphicLayers([IdMap<PaintList>; Order::COUNT]);
201
202impl GraphicLayers {
203 pub fn entry(&mut self, layer_id: LayerId) -> &mut PaintList {
205 self.0[layer_id.order as usize]
206 .entry(layer_id.id)
207 .or_default()
208 }
209
210 pub fn get(&self, layer_id: LayerId) -> Option<&PaintList> {
212 self.0[layer_id.order as usize].get(&layer_id.id)
213 }
214
215 pub fn get_mut(&mut self, layer_id: LayerId) -> Option<&mut PaintList> {
217 self.0[layer_id.order as usize].get_mut(&layer_id.id)
218 }
219
220 pub fn drain(
221 &mut self,
222 area_order: &[LayerId],
223 to_global: &ahash::HashMap<LayerId, TSTransform>,
224 ) -> Vec<ClippedShape> {
225 profiling::function_scope!();
226
227 let mut all_shapes: Vec<_> = Default::default();
228
229 for &order in &Order::ALL {
230 let order_map = &mut self.0[order as usize];
231
232 order_map.retain(|_, list| !list.is_empty());
236
237 for layer_id in area_order {
239 if layer_id.order == order {
240 if let Some(list) = order_map.get_mut(&layer_id.id) {
241 if let Some(to_global) = to_global.get(layer_id) {
242 for clipped_shape in &mut list.0 {
243 clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
244 clipped_shape.shape.transform(*to_global);
245 }
246 }
247 all_shapes.append(&mut list.0);
248 }
249 }
250 }
251
252 for (id, list) in order_map {
254 let layer_id = LayerId::new(order, *id);
255
256 if let Some(to_global) = to_global.get(&layer_id) {
257 for clipped_shape in &mut list.0 {
258 clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
259 clipped_shape.shape.transform(*to_global);
260 }
261 }
262
263 all_shapes.append(&mut list.0);
264 }
265 }
266
267 all_shapes
268 }
269}