nightshade 0.8.0

A cross-platform data-oriented game engine.
Documentation
use crate::editor::selection::EntitySelection;
use crate::prelude::*;
use nalgebra_glm::Vec2;

pub enum EntityContextAction {
    None,
    Grab,
    Rotate,
    Scale,
    Duplicate,
    Delete,
    Copy,
    Paste,
    FocusView,
}

pub struct EntityContextResult {
    pub close_popup: bool,
    pub action: EntityContextAction,
}

pub fn entity_context_menu_ui(
    ui_context: &egui::Context,
    world: &World,
    selection: &EntitySelection,
    popup_pos: Vec2,
) -> EntityContextResult {
    let Some(entity) = selection.primary() else {
        return EntityContextResult {
            close_popup: true,
            action: EntityContextAction::None,
        };
    };

    let entity_name = world
        .get_name(entity)
        .map(|n| n.0.clone())
        .unwrap_or_else(|| format!("Entity {}", entity.id));

    let mut close_popup = false;
    let mut action = EntityContextAction::None;

    let area_response = egui::Area::new(egui::Id::new("entity_context_menu"))
        .fixed_pos(egui::pos2(popup_pos.x, popup_pos.y))
        .order(egui::Order::Foreground)
        .show(ui_context, |ui| {
            egui::Frame::popup(ui.style()).show(ui, |ui| {
                ui.set_min_width(160.0);
                ui.label(&entity_name);
                ui.separator();

                if context_menu_row(ui, "Grab", "G") {
                    action = EntityContextAction::Grab;
                    close_popup = true;
                }
                if context_menu_row(ui, "Rotate", "R") {
                    action = EntityContextAction::Rotate;
                    close_popup = true;
                }
                if context_menu_row(ui, "Scale", "S") {
                    action = EntityContextAction::Scale;
                    close_popup = true;
                }
                ui.separator();
                if context_menu_row(ui, "Duplicate", "Shift+D") {
                    action = EntityContextAction::Duplicate;
                    close_popup = true;
                }
                if context_menu_row(ui, "Delete", "X") {
                    action = EntityContextAction::Delete;
                    close_popup = true;
                }
                ui.separator();
                if context_menu_row(ui, "Copy", "Ctrl+C") {
                    action = EntityContextAction::Copy;
                    close_popup = true;
                }
                if context_menu_row(ui, "Paste", "Ctrl+V") {
                    action = EntityContextAction::Paste;
                    close_popup = true;
                }
                if context_menu_row(ui, "Focus View", "F") {
                    action = EntityContextAction::FocusView;
                    close_popup = true;
                }
            });
        });

    if super::should_dismiss_popup(ui_context, area_response.response.rect, close_popup) {
        close_popup = true;
    }

    EntityContextResult {
        close_popup,
        action,
    }
}

fn context_menu_row(ui: &mut egui::Ui, label: &str, shortcut: &str) -> bool {
    ui.horizontal(|ui| {
        let clicked = ui.button(label).clicked();
        ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
            ui.label(egui::RichText::new(shortcut).weak().small());
        });
        clicked
    })
    .inner
}