nightshade-editor 0.13.4

An interactive editor for the Nightshade game engine
use crate::dev_tools::{spawn_3d_text, spawn_lines, spawn_meshes, spawn_text_lattice};
use crate::engine_editor::EditorContext;
use crate::widgets::{EditorWidget, sorted_camera_entities};
use nightshade::prelude::*;

pub fn tools_menu_ui(
    context: &mut EditorContext,
    #[cfg(not(target_arch = "wasm32"))] notifications: &mut Vec<(crate::mosaic::ToastKind, String)>,
    mosaic: &mut crate::EditorMosaic,
    world: &mut World,
    ui: &mut egui::Ui,
) {
    if ui.button("Clear Scene").clicked() {
        crate::project_io::clear_scene(context, world);
        ui.close();
    }

    ui.separator();

    let cameras = sorted_camera_entities(world);
    let camera_count = cameras.len();
    if ui
        .add_enabled(
            camera_count > 0,
            egui::Button::new(format!("Show All Cameras ({})", camera_count)),
        )
        .clicked()
    {
        let mut tiles = egui_tiles::Tiles::default();
        let viewport_ids: Vec<_> = cameras
            .iter()
            .enumerate()
            .map(|(index, _)| {
                tiles.insert_pane(crate::mosaic::Pane::new(EditorWidget::Camera(
                    crate::widgets::CameraWidget {
                        camera_index: index,
                    },
                )))
            })
            .collect();

        let root = if viewport_ids.len() == 1 {
            viewport_ids[0]
        } else {
            tiles.insert_grid_tile(viewport_ids)
        };

        mosaic.set_tree(egui_tiles::Tree::new("tile_tree", root, tiles));
        ui.close();
    }

    ui.separator();

    create_submenu(ui, world);

    #[cfg(not(target_arch = "wasm32"))]
    {
        ui.separator();
        if ui
            .button("Import FBX")
            .on_hover_text("Import an FBX file with meshes and animations")
            .clicked()
        {
            notifications.extend(crate::engine_editor::import_fbx(world));
            ui.close();
        }

        let has_animation_player = context
            .selection
            .primary()
            .map(|entity| {
                world
                    .core
                    .entity_has_components(entity, nightshade::ecs::world::ANIMATION_PLAYER)
            })
            .unwrap_or(false);

        if ui
            .add_enabled(has_animation_player, egui::Button::new("Import Animation"))
            .on_hover_text(
                "Import animations from FBX and add to selected entity's AnimationPlayer",
            )
            .on_disabled_hover_text("Select an entity with an AnimationPlayer first")
            .clicked()
        {
            notifications.extend(crate::engine_editor::import_animation(
                &context.selection,
                world,
            ));
            ui.close();
        }
    }

    {
        ui.separator();
        ui.label("Tests");
        ui.separator();

        ui.label("Line Scaling Test:");
        if ui.button("Spawn 2,000 Lines").clicked() {
            spawn_lines(world);
        }
        ui.separator();
        ui.label("Mesh Scaling Test:");
        if ui.button("Spawn 10,000 Meshes").clicked() {
            spawn_meshes(world);
        }
        ui.separator();
        ui.label("Text Test:");
        if ui.button("Spawn 3D Text").clicked() {
            spawn_3d_text(world);
        }
        if ui.button("Spawn 5K Text Lattice (Stress Test)").clicked() {
            spawn_text_lattice(world);
        }
    }

    ui.separator();
    gizmo_mode_menu(ui, context, world);
}

fn create_submenu(ui: &mut egui::Ui, world: &mut World) {
    ui.menu_button("Create", |ui| {
        ui.set_min_width(150.0);

        ui.label("Lighting");
        if ui.button("Sun").clicked() {
            spawn_sun(world);
            ui.close();
        }
        ui.separator();

        ui.label("Primitives");
        if ui.button("Cube").clicked() {
            spawn_cube_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        if ui.button("Sphere").clicked() {
            spawn_sphere_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        if ui.button("Cylinder").clicked() {
            spawn_cylinder_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        if ui.button("Torus").clicked() {
            spawn_torus_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        if ui.button("Cone").clicked() {
            spawn_cone_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        if ui.button("Plane").clicked() {
            spawn_plane_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
        ui.separator();

        ui.label("Special");
        if ui.button("Water Plane").clicked() {
            spawn_water_plane_at(world, Vec3::new(0.0, 0.0, 0.0));
            ui.close();
        }
    });
}

fn gizmo_mode_menu(ui: &mut egui::Ui, context: &mut EditorContext, world: &mut World) {
    let old_mode = context.gizmo_interaction.mode;
    ui.menu_button(
        format!("Gizmo: {:?}", context.gizmo_interaction.mode),
        |ui| {
            if ui
                .selectable_label(
                    context.gizmo_interaction.mode
                        == nightshade::ecs::gizmos::GizmoMode::LocalTranslation,
                    "Local Translation",
                )
                .clicked()
            {
                context.gizmo_interaction.mode =
                    nightshade::ecs::gizmos::GizmoMode::LocalTranslation;
                ui.close();
            }
            if ui
                .selectable_label(
                    context.gizmo_interaction.mode
                        == nightshade::ecs::gizmos::GizmoMode::GlobalTranslation,
                    "Global Translation",
                )
                .clicked()
            {
                context.gizmo_interaction.mode =
                    nightshade::ecs::gizmos::GizmoMode::GlobalTranslation;
                ui.close();
            }
            if ui
                .selectable_label(
                    context.gizmo_interaction.mode == nightshade::ecs::gizmos::GizmoMode::Rotation,
                    "Rotation",
                )
                .clicked()
            {
                context.gizmo_interaction.mode = nightshade::ecs::gizmos::GizmoMode::Rotation;
                ui.close();
            }
            if ui
                .selectable_label(
                    context.gizmo_interaction.mode == nightshade::ecs::gizmos::GizmoMode::Scale,
                    "Scale",
                )
                .clicked()
            {
                context.gizmo_interaction.mode = nightshade::ecs::gizmos::GizmoMode::Scale;
                ui.close();
            }
        },
    );
    if old_mode != context.gizmo_interaction.mode {
        crate::engine_editor::recreate_gizmo_for_mode(context, world);
    }
}