nightshade-editor 0.13.1

An interactive editor for the Nightshade game engine
use crate::engine_editor::selection::EntitySelection;
use crate::engine_editor::undo::UndoHistory;
use crate::project_io::ProjectState;
use nightshade::prelude::*;

pub fn animations_panel_ui(
    ui_context: &egui::Context,
    world: &mut World,
    show_window: &mut bool,
    selection: &mut EntitySelection,
    undo_history: &mut UndoHistory,
    project_state: &mut ProjectState,
    tree_dirty: &mut bool,
) {
    if !*show_window {
        return;
    }

    let mut window_open = *show_window;
    let mut prefab_to_spawn: Option<String> = None;

    let prefab_names: Vec<String> =
        nightshade::ecs::prefab::resources::prefab_cache_names(&world.resources.prefab_cache)
            .cloned()
            .collect();

    let animation_names: Vec<String> =
        nightshade::ecs::prefab::resources::animation_cache_names(&world.resources.animation_cache)
            .cloned()
            .collect();

    egui::Window::new("Animations & Prefabs")
        .open(&mut window_open)
        .default_width(400.0)
        .default_height(500.0)
        .resizable(true)
        .show(ui_context, |ui| {
            ui.heading("Cached Prefabs");
            ui.separator();

            if prefab_names.is_empty() {
                ui.label("No prefabs cached");
                ui.label("Load FBX files to import prefabs");
            } else {
                egui::ScrollArea::vertical()
                    .id_salt("prefabs_scroll")
                    .max_height(200.0)
                    .show(ui, |ui| {
                        for name in &prefab_names {
                            ui.horizontal(|ui| {
                                if ui.button("Spawn").clicked() {
                                    prefab_to_spawn = Some(name.clone());
                                }
                                ui.label(name);
                            });
                        }
                    });
            }

            ui.add_space(10.0);
            ui.heading("Cached Animations");
            ui.separator();

            if animation_names.is_empty() {
                ui.label("No animations cached");
                ui.label("Load FBX files to import animations");
            } else {
                ui.label(format!("{} animations available", animation_names.len()));
                ui.label("Add animations to entities via the Animation Player inspector");
                ui.add_space(5.0);

                egui::ScrollArea::vertical()
                    .id_salt("animations_scroll")
                    .max_height(200.0)
                    .show(ui, |ui| {
                        for name in &animation_names {
                            ui.label(format!("  {}", name));
                        }
                    });
            }
        });

    *show_window = window_open;

    let Some(prefab_name) = prefab_to_spawn else {
        return;
    };
    let Some(cached) = world.resources.prefab_cache.prefabs.get(&prefab_name) else {
        return;
    };
    let prefab = cached.prefab.clone();
    let animations = cached.animations.clone();
    let skins = cached.skins.clone();
    let source_path = cached.source_path.clone();

    let entity = nightshade::ecs::prefab::spawn_prefab_with_source(
        world,
        &prefab,
        &animations,
        &skins,
        nalgebra_glm::vec3(0.0, 0.0, 0.0),
        source_path.as_deref(),
    );
    let hierarchy = Box::new(crate::engine_editor::capture_hierarchy(world, entity));
    undo_history.push(
        crate::engine_editor::UndoableOperation::EntityCreated {
            hierarchy,
            current_entity: entity,
        },
        format!("Spawn prefab {}", prefab_name),
    );
    selection.set_single(entity);
    *tree_dirty = true;
    project_state.mark_modified();
}