1use operad::{
2 layout, root_style, ApproxTextMeasurer, ClipBehavior, ColorRgba, InputBehavior, ScrollAxes,
3 StrokeStyle, TextStyle, UiDocument, UiInputEvent, UiNode, UiNodeStyle, UiPoint, UiSize,
4 UiVisual,
5};
6
7fn main() {
8 let probes = [
9 ("game_hud", build_game_hud()),
10 ("fabricad_panel", build_fabricad_panel()),
11 ("orbifold_editor", build_orbifold_editor()),
12 ];
13
14 for (name, mut document) in probes {
15 document
16 .compute_layout(UiSize::new(800.0, 600.0), &mut ApproxTextMeasurer)
17 .expect("probe layout should compute");
18 assert!(
19 document.audit_layout().is_empty(),
20 "{name} should have no basic layout audit warnings"
21 );
22 assert!(
23 !document.paint_list().is_empty(),
24 "{name} should produce renderer-neutral paint"
25 );
26 println!("{name}: {} paint items", document.paint_list().items.len());
27 }
28}
29
30fn build_game_hud() -> UiDocument {
31 let mut document = UiDocument::new(root_style(800.0, 600.0));
32 let hotbar = document.add_child(
33 document.root,
34 UiNode::container(
35 "game.hotbar",
36 UiNodeStyle {
37 clip: ClipBehavior::Clip,
38 z_index: 10,
39 ..layout::node_style(layout::with_margin_bottom(
40 layout::with_auto_horizontal_margin(layout::with_size(
41 layout::centered_row(),
42 layout::px(360.0),
43 layout::px(64.0),
44 )),
45 18.0,
46 ))
47 },
48 )
49 .with_visual(UiVisual::panel(
50 ColorRgba::new(20, 24, 31, 230),
51 Some(StrokeStyle::new(ColorRgba::new(96, 113, 139, 255), 1.0)),
52 6.0,
53 )),
54 );
55
56 for slot in 0..8 {
57 document.add_child(
58 hotbar,
59 UiNode::container(
60 format!("game.hotbar.slot.{slot}"),
61 layout::node_style(layout::with_margin_all(layout::fixed(36.0, 36.0), 4.0)),
62 )
63 .with_input(InputBehavior::BUTTON)
64 .with_visual(UiVisual::panel(
65 ColorRgba::new(40, 49, 62, 255),
66 Some(StrokeStyle::new(ColorRgba::new(105, 124, 153, 255), 1.0)),
67 4.0,
68 )),
69 );
70 }
71
72 document
73}
74
75fn build_fabricad_panel() -> UiDocument {
76 let mut document = UiDocument::new(root_style(800.0, 600.0));
77 let panel = document.add_child(
78 document.root,
79 UiNode::container(
80 "fabricad.sidebar.modules",
81 UiNodeStyle {
82 clip: ClipBehavior::Clip,
83 ..layout::node_style(layout::with_size(
84 layout::column(),
85 layout::px(260.0),
86 layout::px(220.0),
87 ))
88 },
89 )
90 .with_scroll(ScrollAxes::VERTICAL)
91 .with_visual(UiVisual::panel(
92 ColorRgba::new(28, 33, 39, 255),
93 Some(StrokeStyle::new(ColorRgba::new(74, 85, 104, 255), 1.0)),
94 4.0,
95 )),
96 );
97
98 for row in 0..12 {
99 document.add_child(
100 panel,
101 UiNode::text(
102 format!("fabricad.module.{row}"),
103 format!("Layer module {row}"),
104 TextStyle::default(),
105 layout::size(layout::percent(1.0), layout::px(32.0)),
106 )
107 .with_input(InputBehavior::BUTTON),
108 );
109 }
110
111 document.handle_input(UiInputEvent::wheel(
112 UiPoint::new(12.0, 12.0),
113 UiPoint::new(0.0, 24.0),
114 ));
115
116 document
117}
118
119fn build_orbifold_editor() -> UiDocument {
120 let mut document = UiDocument::new(root_style(800.0, 600.0));
121 let shell = document.add_child(
122 document.root,
123 UiNode::container(
124 "orbifold.shell",
125 UiNodeStyle {
126 clip: ClipBehavior::Clip,
127 ..layout::node_style(layout::with_size(
128 layout::column(),
129 layout::percent(1.0),
130 layout::percent(1.0),
131 ))
132 },
133 ),
134 );
135
136 document.add_child(
137 shell,
138 UiNode::text(
139 "orbifold.transport",
140 "Transport",
141 TextStyle::default(),
142 layout::size(layout::percent(1.0), layout::px(32.0)),
143 )
144 .with_visual(UiVisual::panel(
145 ColorRgba::new(30, 36, 44, 255),
146 Some(StrokeStyle::new(ColorRgba::new(84, 96, 115, 255), 1.0)),
147 0.0,
148 )),
149 );
150 document.add_child(
151 shell,
152 UiNode::canvas(
153 "orbifold.piano_roll",
154 "orbifold.piano_roll.display_list_surface",
155 layout::size(layout::percent(1.0), layout::px(260.0)),
156 )
157 .with_visual(UiVisual::panel(
158 ColorRgba::new(16, 19, 23, 255),
159 Some(StrokeStyle::new(ColorRgba::new(64, 75, 92, 255), 1.0)),
160 0.0,
161 )),
162 );
163
164 document
165}