1use libdqg::input::{InputState, MouseState};
2use libdqg::renderer::{DrawPass, Renderer};
3use libdqg::scene::{Scene, SceneTransition};
4
5use crate::editor_scene::{EditorScene, PendingAction};
6use crate::egui_layer::EguiLayer;
7use crate::recent_projects::RecentProjects;
8
9pub struct MenuScene {
12 egui: EguiLayer,
13 recent: RecentProjects,
14}
15
16impl MenuScene {
17 pub fn new() -> Self {
18 Self { egui: EguiLayer::new(), recent: RecentProjects::load() }
19 }
20}
21
22impl Scene for MenuScene {
23 fn update(
24 &mut self,
25 _delta_time: f32,
26 _input_state: &InputState,
27 _mouse_state: &MouseState,
28 renderer: Option<&mut Renderer>,
29 ) -> SceneTransition {
30 let Some(renderer) = renderer else { return SceneTransition::None };
31
32 let recent = &self.recent;
33 let mut action = None;
34 self.egui.run(renderer, |ui| {
35 action = draw(ui, recent);
36 });
37
38 match action {
39 Some(action) => SceneTransition::Replace(Box::new(EditorScene::opening(action))),
40 None => SceneTransition::None,
41 }
42 }
43
44 fn render(&mut self, _pass: &mut DrawPass) {}
45
46 fn on_window_event(&mut self, event: &winit::event::WindowEvent) {
47 self.egui.on_window_event(event);
48 }
49
50 fn render_overlay(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView) {
51 self.egui.render_overlay(device, queue, encoder, view);
52 }
53}
54
55fn draw(ui: &mut egui::Ui, recent: &RecentProjects) -> Option<PendingAction> {
56 let mut action = None;
57
58 egui::CentralPanel::default().show(ui, |ui| {
59 ui.vertical_centered(|ui| {
60 ui.add_space(48.0);
61 ui.heading("libDQG Editor");
62 ui.add_space(24.0);
63
64 ui.horizontal(|ui| {
65 if ui.button("New Project...").clicked() {
66 if let Some(root) = rfd::FileDialog::new().pick_folder() {
67 action = Some(PendingAction::New(root));
68 }
69 }
70 if ui.button("Open Project...").clicked() {
71 if let Some(root) = rfd::FileDialog::new().pick_folder() {
72 action = Some(PendingAction::Open(root));
73 }
74 }
75 });
76
77 ui.add_space(32.0);
78 ui.separator();
79 ui.add_space(8.0);
80 ui.label("Recent Projects");
81
82 if recent.roots.is_empty() {
83 ui.weak("No recent projects.");
84 }
85
86 egui::ScrollArea::vertical().max_height(300.0).show(ui, |ui| {
87 for root in &recent.roots {
88 let name = root
89 .file_name()
90 .map(|n| n.to_string_lossy().into_owned())
91 .unwrap_or_else(|| root.display().to_string());
92 ui.group(|ui| {
93 ui.vertical(|ui| {
94 if ui.selectable_label(false, name).clicked() {
95 action = Some(PendingAction::Open(root.clone()));
96 }
97 ui.weak(root.display().to_string());
98 });
99 });
100 }
101 });
102 });
103 });
104
105 action
106}