Skip to content

Commit 7ee6407

Browse files
committed
clean up ui code a bit and create a separate left panel component
1 parent 02f6093 commit 7ee6407

10 files changed

Lines changed: 413 additions & 416 deletions

File tree

src/bin/drawing/ui.rs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
pub mod state;
2+
pub mod views;
3+
pub mod widgets;
4+
5+
use crate::app_state::AppState;
6+
use egui::vec2;
7+
use egui::Color32;
8+
use egui::FontDefinitions;
9+
use egui::Layout;
10+
use egui::Style;
11+
use egui::Visuals;
12+
use egui_wgpu_backend::RenderPass;
13+
use egui_wgpu_backend::ScreenDescriptor;
14+
use egui_winit_platform::PlatformDescriptor;
15+
use views::fps::view_fps;
16+
use views::location_finder::LocationFinderWindow;
17+
use views::panel_left::PanelLeft;
18+
use views::panel_right::panel_right;
19+
use wgpu::SurfaceConfiguration;
20+
21+
pub struct Hud {
22+
pub(crate) platform: egui_winit_platform::Platform,
23+
rpass: RenderPass,
24+
ui: HudUi,
25+
}
26+
27+
impl Hud {
28+
pub fn new(
29+
window: &winit::window::Window,
30+
device: &mut wgpu::Device,
31+
surface_config: &SurfaceConfiguration,
32+
) -> Self {
33+
// We use the egui_winit_platform crate as the platform.
34+
let size = window.inner_size();
35+
let platform = egui_winit_platform::Platform::new(PlatformDescriptor {
36+
physical_width: size.width,
37+
physical_height: size.height,
38+
scale_factor: window.scale_factor(),
39+
font_definitions: FontDefinitions::default(),
40+
style: Default::default(),
41+
});
42+
43+
let style = Style {
44+
visuals: Visuals {
45+
override_text_color: Some(Color32::WHITE),
46+
..Visuals::dark()
47+
},
48+
..Style::default()
49+
};
50+
platform.context().set_style(style);
51+
52+
// We use the egui_wgpu_backend crate as the render backend.
53+
let rpass = RenderPass::new(device, surface_config.format, 1);
54+
55+
let ui = HudUi {
56+
location_finder_window: LocationFinderWindow::new(false),
57+
side_panel: PanelLeft::new(),
58+
};
59+
60+
Self {
61+
platform,
62+
rpass,
63+
ui,
64+
}
65+
}
66+
67+
pub fn paint(
68+
&mut self,
69+
app_state: &mut AppState,
70+
window: &winit::window::Window,
71+
device: &mut wgpu::Device,
72+
queue: &wgpu::Queue,
73+
encoder: &mut wgpu::CommandEncoder,
74+
frame: &wgpu::SurfaceTexture,
75+
) {
76+
let view = frame
77+
.texture
78+
.create_view(&wgpu::TextureViewDescriptor::default());
79+
80+
self.platform.context().set_pixels_per_point(4.0);
81+
// Begin to draw the UI frame.
82+
self.platform.begin_pass();
83+
84+
// Draw the demo application.
85+
self.ui.ui(&self.platform.context(), app_state);
86+
87+
// End the UI frame. We could now handle the output and draw the UI with the backend.
88+
let full_output = self.platform.end_pass(Some(window));
89+
let paint_jobs = self.platform.context().tessellate(
90+
full_output.shapes,
91+
self.platform.context().pixels_per_point(),
92+
);
93+
94+
// Upload all resources for the GPU.
95+
let size = window.inner_size();
96+
let screen_descriptor = ScreenDescriptor {
97+
physical_width: size.width,
98+
physical_height: size.height,
99+
scale_factor: window.scale_factor() as f32,
100+
};
101+
let tdelta: egui::TexturesDelta = full_output.textures_delta;
102+
self.rpass
103+
.add_textures(device, queue, &tdelta)
104+
.expect("add texture ok");
105+
self.rpass
106+
.update_buffers(device, queue, &paint_jobs, &screen_descriptor);
107+
108+
// Record all render passes.
109+
self.rpass
110+
.execute(encoder, &view, &paint_jobs, &screen_descriptor, None)
111+
.unwrap();
112+
self.rpass
113+
.remove_textures(tdelta)
114+
.expect("remove texture ok");
115+
}
116+
117+
pub fn interact(&mut self, event: &winit::event::WindowEvent) -> bool {
118+
self.platform.handle_event(event);
119+
self.platform.captures_event(event) || self.platform.context().is_pointer_over_area()
120+
}
121+
}
122+
123+
struct HudUi {
124+
location_finder_window: LocationFinderWindow,
125+
side_panel: PanelLeft,
126+
}
127+
128+
impl HudUi {
129+
pub fn ui(&mut self, ctx: &egui::Context, app_state: &mut AppState) {
130+
{
131+
let pointer_position = ctx.input(|i| i.pointer.hover_pos()).unwrap_or_default();
132+
133+
// This should have precedence for grabbing keystrokes when it's open.
134+
self.location_finder_window.ui(ctx, app_state);
135+
136+
// Draw menubar.
137+
egui::TopBottomPanel::top("Main Menu Bar").show(ctx, |ui| {
138+
ui.horizontal_centered(|ui| {
139+
// Take full width and fixed height:
140+
let height = ui.spacing().interact_size.y;
141+
ui.style_mut().spacing.button_padding = vec2(2.0, 0.0);
142+
ui.set_min_size(vec2(ui.available_width(), height));
143+
ui.menu_button("File", |ui| {
144+
if ui.button("Quit").clicked() {
145+
ui.close_menu();
146+
}
147+
});
148+
ui.with_layout(Layout::right_to_left(egui::Align::Center), |ui| {
149+
ui.label(format!(
150+
"Frametime {:.2?} at zoom {:.2}",
151+
app_state.stats.get_average(),
152+
app_state.zoom
153+
));
154+
155+
ui.label(format!(
156+
"Mouse Position: ({:.1},{:.1})",
157+
pointer_position[0], pointer_position[1]
158+
));
159+
160+
view_fps(ui, app_state);
161+
})
162+
})
163+
});
164+
165+
panel_right(ctx, app_state);
166+
167+
self.side_panel.ui(ctx, app_state);
168+
}
169+
}
170+
}

0 commit comments

Comments
 (0)