use bevy_gearbox_protocol::components as c;
use crate::model::StateMachineGraph;
use crate::types::EntityId;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MenuItemKind {
MakeLeaf,
MakeParent,
MakeParallel,
Rename,
Save,
SaveSubstates,
Delete,
MakeInitial { parent: EntityId },
AddChild,
AutoLayout,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MenuItem {
pub label: &'static str,
pub kind: MenuItemKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MenuSelection {
MakeLeaf { target: EntityId },
MakeParent { target: EntityId },
MakeParallel { target: EntityId },
RenameEntity { target: EntityId },
SaveStateMachine { target: EntityId },
SaveSubstates { target: EntityId },
DeleteEntity { target: EntityId },
MakeInitial { parent: EntityId, new_initial: EntityId },
AddChildStateMachine { target: EntityId },
AutoLayoutSubtree { target: EntityId },
}
pub fn build_context_menu(graph: &StateMachineGraph, id: EntityId) -> Vec<MenuItem> {
let mut items: Vec<MenuItem> = Vec::new();
if !graph.nodes.contains_key(&id) { return items; }
let has_children = !graph.get_children(&id).is_empty();
let has_initial_state = graph.has_component(&id, c::INITIAL_STATE);
let is_parallel = has_children && !has_initial_state;
let has_state_children_capability = graph.has_component(&id, c::STATE_CHILDREN);
let parent_and_lacks_initial = graph.get_parent(&id).and_then(|pid| (!graph.has_component(&pid, c::INITIAL_STATE)).then_some(pid));
if has_children {
items.push(MenuItem { label: "Make Leaf", kind: MenuItemKind::MakeLeaf });
}
if !has_initial_state {
items.push(MenuItem { label: "Make Parent", kind: MenuItemKind::MakeParent });
}
if !is_parallel {
items.push(MenuItem { label: "Make Parallel", kind: MenuItemKind::MakeParallel });
}
items.push(MenuItem { label: "Save As", kind: MenuItemKind::Save });
let mut has_descendant_with_id = false;
if has_children {
let mut stack: Vec<EntityId> = graph.get_children(&id);
while let Some(cid) = stack.pop() {
if graph.entity_data.get(&cid).map(|b| b.contains(c::STATE_MACHINE_ID)).unwrap_or(false) { has_descendant_with_id = true; break; }
let kids = graph.get_children(&cid);
if !kids.is_empty() { stack.extend(kids.into_iter()); }
}
}
if has_descendant_with_id {
items.push(MenuItem { label: "Save Substates", kind: MenuItemKind::SaveSubstates });
}
items.push(MenuItem { label: "Rename", kind: MenuItemKind::Rename });
items.push(MenuItem { label: "Delete", kind: MenuItemKind::Delete });
if let Some(parent) = parent_and_lacks_initial {
items.push(MenuItem { label: "Make Initial", kind: MenuItemKind::MakeInitial { parent } });
}
if has_state_children_capability {
items.push(MenuItem { label: "Add Child", kind: MenuItemKind::AddChild });
}
items.push(MenuItem { label: "Auto Layout", kind: MenuItemKind::AutoLayout });
items
}