nightshade-editor 0.13.4

An interactive editor for the Nightshade game engine
use crate::Editor;
#[cfg(not(target_arch = "wasm32"))]
use crate::mosaic::ToastKind;
use nightshade::prelude::*;

impl Editor {
    #[cfg(not(target_arch = "wasm32"))]
    pub fn update_window_title(&self, world: &World) {
        let window_title = crate::mosaic::format_window_title(
            "Nightshade Editor",
            self.context.project_edit.current_path.as_deref(),
            self.project_state.is_modified,
        );

        if let Some(window_handle) = &world.resources.window.handle {
            window_handle.set_title(&window_title);
        }
    }

    pub fn top_panel_ui(&mut self, world: &mut World, root_ui: &mut egui::Ui) {
        egui::Panel::top("top").show_inside(root_ui, |ui| {
            ui.horizontal(|ui| {
                egui::MenuBar::new().ui(ui, |ui| {
                    #[cfg(not(target_arch = "wasm32"))]
                    {
                        self.project_name_editing_ui(world, ui);
                        ui.separator();
                        self.process_layout_events(ui);
                    }

                    #[cfg(target_arch = "wasm32")]
                    {
                        let light_green = egui::Color32::from_rgb(144, 238, 144);
                        ui.menu_button(
                            egui::RichText::new("🔨 Project").color(light_green),
                            |ui| {
                                if ui.button("New Project").clicked() {
                                    self.new_project(world);
                                    ui.close();
                                }
                                ui.separator();
                                if ui.button("Save Project...").clicked() {
                                    self.save_project(world);
                                    ui.close();
                                }
                                if ui.button("Load Project...").clicked() {
                                    self.load_project(world);
                                    ui.close();
                                }
                            },
                        );
                    }

                    ui.separator();
                    ui.menu_button("View", |ui| {
                        super::view_menu::view_menu_ui(
                            &mut self.context.ui.visibility,
                            &mut self.theme_state,
                            #[cfg(not(target_arch = "wasm32"))]
                            &mut self.settings,
                            #[cfg(not(target_arch = "wasm32"))]
                            &mut self.toasts,
                            world,
                            ui,
                        );
                    });
                    ui.separator();
                    ui.menu_button("Tools", |ui| {
                        super::tools_menu::tools_menu_ui(
                            &mut self.context.editor,
                            #[cfg(not(target_arch = "wasm32"))]
                            &mut self.context.notifications,
                            &mut self.mosaic,
                            world,
                            ui,
                        );
                    });
                    ui.separator();

                    self.status_bar_ui(world, ui);
                });
            });
        });
    }

    #[cfg(not(target_arch = "wasm32"))]
    fn project_name_editing_ui(&mut self, world: &mut World, ui: &mut egui::Ui) {
        if self.context.project_edit.editing_name {
            ui.horizontal(|ui| {
                ui.add(
                    egui::TextEdit::singleline(&mut self.context.project_edit.name_edit_buffer)
                        .desired_width(150.0),
                );

                if ui.button("").clicked() {
                    self.context.project_edit.editing_name = false;
                    self.context.project_edit.name_edit_buffer.clear();
                }

                if ui.button("").clicked() {
                    if !self.context.project_edit.name_edit_buffer.trim().is_empty() {
                        let new_name = self
                            .context
                            .project_edit
                            .name_edit_buffer
                            .trim()
                            .to_string();
                        self.context.project_edit.current_name = Some(new_name.clone());
                        if let Some(ref mut project) = self.project {
                            project.name = new_name;
                        }
                        self.project_state.mark_modified();
                    }
                    self.context.project_edit.editing_name = false;
                    self.context.project_edit.name_edit_buffer.clear();
                }
            });
        } else {
            self.display_project_menu(world, ui);
        }
    }

    #[cfg(not(target_arch = "wasm32"))]
    fn process_layout_events(&mut self, ui: &mut egui::Ui) {
        let events = self
            .mosaic
            .render_layout_section(ui, crate::project_io::create_default_tile_tree);
        for event in events {
            use crate::mosaic::LayoutEvent;
            let (modifies_project, message) = match &event {
                LayoutEvent::Switched(name) => (false, format!("Switched to layout: {}", name)),
                LayoutEvent::Created(name) => (true, format!("Created layout: {}", name)),
                LayoutEvent::Saved(name) => (true, format!("Saved layout: {}", name)),
                LayoutEvent::Deleted(name) => (true, format!("Deleted layout: {}", name)),
                LayoutEvent::Reset => (true, "Reset layout to default".to_string()),
                LayoutEvent::Renamed(name) => (true, format!("Renamed layout: {}", name)),
            };
            if modifies_project {
                self.project_state.mark_modified();
            }
            self.toasts.push(ToastKind::Success, message, 3.0);
        }
    }

    fn status_bar_ui(&mut self, world: &mut World, ui: &mut egui::Ui) {
        ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
            let _ = ui.small_button(
                egui::RichText::new(format!("🏷 v{}", env!("CARGO_PKG_VERSION")))
                    .color(egui::Color32::from_rgb(255, 145, 0))
                    .strong(),
            );
            ui.separator();
            ui.label(format!(
                "FPS: {}",
                world.resources.window.timing.frames_per_second
            ));
            ui.separator();

            let unlit = world.resources.graphics.unlit_mode;
            if ui
                .selectable_label(unlit, "Unlit")
                .on_hover_text("Flat shading without lighting (CAD mode)")
                .clicked()
            {
                world.resources.graphics.unlit_mode = true;
            }
            if ui
                .selectable_label(!unlit, "Lit")
                .on_hover_text("Full PBR lighting")
                .clicked()
            {
                world.resources.graphics.unlit_mode = false;
            }
            ui.separator();

            #[cfg(not(target_arch = "wasm32"))]
            if ui
                .button("📷")
                .on_hover_text("Capture screenshot (saves to screenshots/ folder)")
                .clicked()
            {
                nightshade::ecs::world::capture_screenshot(world);
            }
            ui.separator();
        });
    }
}