GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
examples/grouped_recess_probe.rs (4.1K)
1 //! A visual check that a recess GROUPED into its plate as a CSG feature
2 //! shades like the same recess drawn as an overlay. Left plate: the recesses
3 //! group (nothing else is painted between the plate and them). Right plate:
4 //! the same recesses, but a transparent quad painted first closes the plate's
5 //! grouping window, so each one falls back to the overlay. The two columns
6 //! should read alike on every device — compare `CCE_VK_DEVICE=discrete`
7 //! against the default. `CCE_PLATE_DEBUG=1` prints the grouping verdicts.
8 //! Run inside a Wayland session (a cce-shadow instance works):
9 //! `cargo run --release -p cce-ui --example grouped_recess_probe`.
10
11 use cce_ui::engine::{AppSender, Application, LogicalPosition, LogicalSize, WindowSettings};
12 use cce_ui::scene::layout::Rect;
13 use cce_ui::scene::paint::{DisplayList, PaintCtx};
14 use cce_ui::scene::Material;
15 use cce_ui::widget::{ElementState, KeyEvent, MouseButton, MouseScrollDelta};
16
17 struct ProbeApp;
18
19 /// The probe's recesses, relative to a plate's top-left: (rect, radius,
20 /// depth) at the sizes the parameter pane uses — a text box, a toggle's
21 /// track, a colour well — and a couple of deeper ones.
22 fn recesses(x: f32, y: f32) -> Vec<(Rect, f32, f32)> {
23 let w = cce_ui::layout::bevel_width();
24 let mut out = Vec::new();
25 let mut yy = y + 30.0;
26 for (h, wide) in [(20.0, 260.0), (20.0, 120.0), (28.0, 260.0), (40.0, 260.0), (70.0, 260.0)] {
27 let depth = w.min(h * 0.2);
28 out.push((Rect { x: x + 30.0, y: yy, width: wide, height: h }, (h * 0.5).min(8.0), depth));
29 yy += h + 24.0;
30 }
31 out
32 }
33
34 impl Application for ProbeApp {
35 type Message = ();
36
37 fn create(_sender: AppSender<()>) -> Self {
38 Self
39 }
40
41 fn settings(&self) -> WindowSettings {
42 WindowSettings {
43 title: "grouped recess probe".into(),
44 app_id: "cce-grouped-recess-probe".into(),
45 width: 720,
46 height: 400,
47 fullscreen: false,
48 min_size: None,
49 }
50 }
51
52 fn update(&mut self, _msg: (), _needs_rebuild: &mut bool, _exit: &mut bool) {}
53
54 fn tick(&mut self, _dt: f32, _needs_rebuild: &mut bool) {}
55
56 fn display_list(&mut self, size: LogicalSize, _scale: f64) -> Option<DisplayList> {
57 let mut pc = PaintCtx::new();
58 let (w, h) = (size.width, size.height);
59 let half = (w - 30.0) * 0.5;
60 let bevel = cce_ui::layout::bevel_width();
61 for (i, x) in [10.0, 20.0 + half].into_iter().enumerate() {
62 let plate = Rect { x, y: 10.0, width: half, height: h - 20.0 };
63 pc.plate(plate, (16.0, 16.0, 16.0, 16.0), &Material::pane(), bevel);
64 if i == 1 {
65 // Ordinary geometry between the plate and its carves closes
66 // the grouping window: every recess below is an overlay.
67 pc.quad(Rect { x: x + 1.0, y: 11.0, width: 1.0, height: 1.0 }, [0.0; 4]);
68 }
69 for (r, radius, depth) in recesses(x, 10.0) {
70 pc.recess(r, (radius, radius, radius, radius), depth);
71 }
72 // A boss, and a recess running into the plate's roll — the
73 // junction grouping exists for (the overlay fades out there
74 // instead, so the two columns differ by design at its right end).
75 let boss = Rect { x: x + 30.0, y: h - 60.0, width: 120.0, height: 30.0 };
76 pc.boss(boss, (8.0, 8.0, 8.0, 8.0), 6.0);
77 let edge = Rect { x: x + 180.0, y: h - 60.0, width: half - 180.0 - 2.0, height: 30.0 };
78 pc.recess(edge, (8.0, 8.0, 8.0, 8.0), 6.0);
79 }
80 Some(pc.finish())
81 }
82
83 fn display_list_text(&self) -> bool {
84 true
85 }
86
87 fn handle_pointer_move(&mut self, _pos: LogicalPosition, _needs_rebuild: &mut bool) {}
88 fn handle_mouse_input(&mut self, _b: MouseButton, _s: ElementState, _p: LogicalPosition, _r: &mut bool) -> Option<()> {
89 None
90 }
91 fn handle_mouse_wheel(&mut self, _d: &MouseScrollDelta, _p: LogicalPosition, _r: &mut bool) {}
92 fn handle_key_input(&mut self, _e: &KeyEvent, _r: &mut bool) -> Option<()> {
93 None
94 }
95 }
96
97 fn main() {
98 cce_ui::engine::run::<ProbeApp>();
99 }