Files
incremental-game-engine/src/ui/graph.ts
T

51 lines
1.5 KiB
TypeScript

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<GraphNode[]> {
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)!,
}));
}