import ELK, { ElkNode } from "elkjs/lib/elk.bundled.js"; import { Unit, Behaviour } from "@incgame/engine"; const elk = new ELK(); const UNIT_WIDTH = 200; const NODE_HEIGHT = 150; export type GraphNode = { position: { x: number, y: number }; kind: 'behaviour'; entity: Behaviour; } export async function build2dNodes(units: Unit[], area: { width: number, height: number, padding: number }): Promise { const entitiesById = new Map(units.map((unit) => [unit.behaviour.id, unit.behaviour])); const graph: ElkNode = { id: "root", layoutOptions: { "elk.algorithm": "layered", "elk.direction": "LEFT", "elk.spacing.nodeNode": "100", "elk.layered.spacing.nodeNodeBetweenLayers": "100", }, children: units.map((unit) => ({ id: unit.behaviour.id, width: UNIT_WIDTH, height: NODE_HEIGHT, })), edges: units.flatMap((node) => node.behaviour.inputLinks.map((link, idx) => ({ id: `${node.behaviour.id}->${link.target}.${idx}`, sources: [node.behaviour.id], targets: [link.target], })) ), }; const layout = await elk.layout(graph); return (layout.children ?? []).map((child) => ({ position: { x: (child.x ?? 0) + area.padding, y: (child.y ?? 0) + area.padding, }, kind: 'behaviour', entity: entitiesById.get(child.id)!, })); }