1use egui::{Color32, Context, Id, LayerId, Order, Rect};
7use std::sync::{Arc, RwLock};
8
9#[derive(Clone, Debug, Default)]
13pub struct OverlayManager(Arc<RwLock<OverlayCounter>>);
14
15impl OverlayManager {
16 pub fn new() -> Self {
18 Self(Arc::new(RwLock::new(OverlayCounter::new())))
19 }
20
21 pub fn tint_0(&self) -> Color32 {
23 Color32::from_black_alpha(40)
24 }
25
26 pub fn tint_1(&self) -> Color32 {
28 Color32::from_black_alpha(60)
29 }
30
31 pub fn tint_2(&self) -> Color32 {
33 Color32::from_black_alpha(80)
34 }
35
36 pub fn tint_3(&self) -> Color32 {
38 Color32::from_black_alpha(100)
39 }
40
41 pub fn counter(&self) -> u8 {
43 self.0.read().unwrap().counter()
44 }
45
46 pub fn order(&self) -> Order {
48 self.0.read().unwrap().order()
49 }
50
51 pub fn paint_background(&self) {
53 self.0.write().unwrap().paint_background()
54 }
55
56 pub fn paint_middle(&self) {
58 self.0.write().unwrap().paint_middle()
59 }
60
61 pub fn paint_foreground(&self) {
63 self.0.write().unwrap().paint_foreground()
64 }
65
66 pub fn paint_tooltip(&self) {
68 self.0.write().unwrap().paint_tooltip()
69 }
70
71 pub fn paint_debug(&self) {
73 self.0.write().unwrap().paint_debug()
74 }
75
76 pub fn window_opened(&self) {
78 self.0.write().unwrap().window_opened();
79 }
80
81 pub fn window_closed(&self) {
83 self.0.write().unwrap().window_closed();
84 }
85
86 pub fn recommended_order(&self) -> Order {
88 self.0.read().unwrap().recommended_order()
89 }
90
91 pub fn calculate_alpha(&self) -> u8 {
93 self.0.read().unwrap().calculate_alpha()
94 }
95
96 pub fn overlay_tint(&self) -> Color32 {
98 self.0.read().unwrap().overlay_tint()
99 }
100
101 pub fn paint_overlay(&self, ctx: &Context, recommend_order: bool) {
105 self.0.read().unwrap().paint_overlay(ctx, recommend_order);
106 }
107
108 pub fn paint_overlay_at(&self, ctx: &Context, rect: Rect, order: Order, id: Id, tint: Color32) {
110 self.0.read().unwrap().paint_overlay_at(ctx, rect, order, id, tint);
111 }
112}
113
114#[derive(Clone, Debug)]
115struct OverlayCounter {
116 counter: u8,
117 order: Order,
118}
119
120impl Default for OverlayCounter {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126impl OverlayCounter {
127 pub fn new() -> Self {
128 Self {
129 counter: 0,
130 order: Order::Background,
131 }
132 }
133
134 pub fn counter(&self) -> u8 {
135 self.counter
136 }
137
138 pub fn order(&self) -> Order {
139 self.order
140 }
141
142 fn paint_background(&mut self) {
143 self.order = Order::Background;
144 }
145
146 fn paint_middle(&mut self) {
147 self.order = Order::Middle;
148 }
149
150 fn paint_foreground(&mut self) {
151 self.order = Order::Foreground;
152 }
153
154 fn paint_tooltip(&mut self) {
155 self.order = Order::Tooltip;
156 }
157
158 fn paint_debug(&mut self) {
159 self.order = Order::Debug;
160 }
161
162 fn window_opened(&mut self) {
163 self.counter += 1;
164 }
165
166 fn window_closed(&mut self) {
167 if self.counter > 0 {
168 self.counter -= 1;
169 }
170 }
171
172 fn calculate_alpha(&self) -> u8 {
173 let counter = self.counter;
174
175 if counter == 0 {
176 return 0;
177 }
178
179 if counter > 3 {
180 return 220;
181 }
182
183 let mut a = 80;
184 for _ in 1..counter {
185 a += 40;
186 }
187
188 a
189 }
190
191 fn overlay_tint(&self) -> Color32 {
192 let counter = self.counter();
193
194 if counter == 1 {
195 return Color32::from_black_alpha(80);
196 }
197
198 let alpha = self.calculate_alpha();
199 Color32::from_black_alpha(alpha)
200 }
201
202 fn recommended_order(&self) -> Order {
203 if self.counter() == 1 {
204 Order::Background
205 } else if self.counter() == 2 {
206 Order::Middle
207 } else {
208 Order::Foreground
209 }
210 }
211
212 fn paint_overlay(&self, ctx: &Context, recommend_order: bool) {
213 let counter = self.counter();
214 if counter == 0 {
215 return;
216 }
217
218 let order = if recommend_order {
219 self.recommended_order()
220 } else {
221 self.order()
222 };
223
224 let layer_id = LayerId::new(order, Id::new("darkening_overlay"));
225
226 let painter = ctx.layer_painter(layer_id);
227 painter.rect_filled(ctx.content_rect(), 0.0, self.overlay_tint());
228 }
229
230 pub fn paint_overlay_at(&self, ctx: &Context, rect: Rect, order: Order, id: Id, tint: Color32) {
231 let layer_id = LayerId::new(order, id);
232
233 let painter = ctx.layer_painter(layer_id);
234 painter.rect_filled(rect, 0.0, tint);
235 }
236}