nightshade-editor 0.13.3

An interactive editor for the Nightshade game engine
use crate::app_context::AssetKey;
use crate::project_io::EditorProjectFile;
use nightshade::prelude::*;

pub struct AssetsWindowResult {
    #[cfg(not(target_arch = "wasm32"))]
    pub scan_requested: bool,
}

pub fn assets_panel_ui(
    ui_context: &egui::Context,
    project: Option<&EditorProjectFile>,
    show_window: &mut bool,
    pending_asset_update: &mut Option<(AssetKey, String)>,
) -> AssetsWindowResult {
    #[cfg_attr(target_arch = "wasm32", allow(unused_mut))]
    let mut result = AssetsWindowResult {
        #[cfg(not(target_arch = "wasm32"))]
        scan_requested: false,
    };

    if !*show_window {
        return result;
    }

    let mut window_open = *show_window;

    egui::Window::new("Assets")
        .open(&mut window_open)
        .default_width(600.0)
        .default_height(400.0)
        .resizable(true)
        .show(ui_context, |ui| {
            #[cfg(not(target_arch = "wasm32"))]
            {
                if ui.button("Scan Assets Directory").clicked() {
                    result.scan_requested = true;
                }
                ui.separator();

                egui::ScrollArea::vertical()
                    .id_salt("assets_scroll")
                    .show(ui, |ui| {
                        if let Some(project) = project {
                            let mut all_prefabs: Vec<(String, String, String, bool)> = Vec::new();

                            let empty = std::collections::HashMap::new();
                            let scenes = project.data.as_ref().map(|d| &d.scenes).unwrap_or(&empty);
                            for (map_name, map) in scenes {
                                if let Some(nightshade::ecs::scene::SceneHdrSkybox::Reference {
                                    path,
                                }) = &map.hdr_skybox
                                {
                                    let exists = std::path::Path::new(path).exists();
                                    all_prefabs.push((
                                        map_name.clone(),
                                        "HDR Skybox".to_string(),
                                        path.clone(),
                                        exists,
                                    ));
                                }
                            }

                            if all_prefabs.is_empty() {
                                ui.label("No referenced assets in project");
                            } else {
                                egui::Grid::new("assets_grid")
                                    .num_columns(5)
                                    .striped(true)
                                    .min_col_width(100.0)
                                    .show(ui, |ui| {
                                        ui.strong("Map");
                                        ui.strong("Asset");
                                        ui.strong("Path");
                                        ui.strong("Status");
                                        ui.strong("Actions");
                                        ui.end_row();

                                        for (map_name, prefab_name, path, exists) in &all_prefabs {
                                            ui.label(map_name);
                                            ui.label(prefab_name);

                                            let path_color = if *exists {
                                                egui::Color32::from_rgb(100, 200, 100)
                                            } else {
                                                egui::Color32::from_rgb(200, 100, 100)
                                            };
                                            ui.label(
                                                egui::RichText::new(path).color(path_color).small(),
                                            );

                                            if *exists {
                                                ui.label(
                                                    egui::RichText::new("Found").color(
                                                        egui::Color32::from_rgb(100, 200, 100),
                                                    ),
                                                );
                                            } else {
                                                ui.label(
                                                    egui::RichText::new("Missing").color(
                                                        egui::Color32::from_rgb(200, 100, 100),
                                                    ),
                                                );
                                            }

                                            ui.horizontal(|ui| {
                                                let asset_filters = [
                                                    nightshade::filesystem::FileFilter {
                                                        name: "GLTF/GLB".to_string(),
                                                        extensions: vec![
                                                            "gltf".to_string(),
                                                            "glb".to_string(),
                                                        ],
                                                    },
                                                    nightshade::filesystem::FileFilter {
                                                        name: "HDR".to_string(),
                                                        extensions: vec!["hdr".to_string()],
                                                    },
                                                ];
                                                if ui.small_button("...").clicked()
                                                    && let Some(new_path) =
                                                        nightshade::filesystem::pick_file(
                                                            &asset_filters,
                                                        )
                                                {
                                                    let new_path_str = new_path
                                                        .canonicalize()
                                                        .ok()
                                                        .and_then(|p| {
                                                            p.to_str().map(|s| s.to_string())
                                                        })
                                                        .unwrap_or_else(|| {
                                                            new_path.display().to_string()
                                                        });
                                                    *pending_asset_update = Some((
                                                        AssetKey::new(
                                                            map_name.clone(),
                                                            prefab_name.clone(),
                                                        ),
                                                        new_path_str,
                                                    ));
                                                }
                                            });

                                            ui.end_row();
                                        }
                                    });
                            }
                        } else {
                            ui.label("No project loaded");
                        }
                    });
            }

            #[cfg(target_arch = "wasm32")]
            {
                let _ = (project, pending_asset_update);
                ui.label("Asset management is not available on web");
            }
        });

    *show_window = window_open;
    result
}