A general-purpose node graph widget for egui.
Build interactive node-based editors with nodes connected by edges for visual programming interfaces, shader editors, DSP graphs, or any graph-based UI.
Note: This library is the basis for nannou-org/gantz. For a more sophisticated example of what can be built with egui_graph, check out gantz.
One of the core design decisions of egui_graph is to avoid requiring that
users model their graph with any particular data structure. The library provides
immediate-mode widgets for rendering and interacting with graphs, but leaves
the underlying data model up to you. Store your graph however makes sense for
your application - whether that's an adjacency list, entity-component system,
or any other representation.
- Interactive Nodes: Drag, select, and delete nodes with intuitive controls
- Edge Creation: Connect nodes via input/output sockets with bezier curve edges
- Multi-Selection: Rectangle selection and Ctrl+click for selecting multiple nodes
- Automatic Layout: Optional graph layout using the
layout-rscrate - Customizable: Configure node flow direction, socket/frame appearance, and more
- Zoom & Pan: Navigate large graphs with mouse controls
- Model-Agnostic: No prescribed graph data structure - use whatever fits your needs
use egui_graph::{Graph, View, Node, NodeId, Edge};
// Create a view to store node and "camera" positions.
let mut view = View::default();
// Show the graph widget
Graph::new("my_graph")
.show(&mut view, ui, |ui, mut show| {
// Add nodes to the graph
show.nodes(|nctx, ui| {
Node::new("node_1")
.inputs(2)
.outputs(1)
.show(nctx, ui, |node_ctx| {
node_ctx.framed(|ui| {
ui.label("My Node");
})
})
});
// Add edges between nodes
show.edges(|ectx, ui| {
let selected = false;
Edge::new(
(NodeId::new("node_1"), 0), // From output 0
(NodeId::new("node_2"), 1), // To input 1
&mut selected
).show(ectx, ui);
});
});Visit the demo.rs example for a more thorough, up-to-date example.
The main widget that contains all nodes and edges:
Graph::new(id_source)
.background(true) // Enable background
.dot_grid(true) // Show dot grid
.zoom_range(0.1..=2.0) // Set zoom limits
.center_view(true) // Center the camera
.show(&mut view, ui, |ui, show| { /* ... */ })Nodes are containers with input/output sockets:
Node::new(id_source)
.inputs(3) // Number of input sockets
.outputs(2) // Number of output sockets
.flow(Direction::LeftToRight) // Socket arrangement
.socket_color(Color32::BLUE)
.socket_radius(5.0)
.show(ctx, ui, |node_ctx| {
// Node content goes here
node_ctx.framed(|ui| {
ui.label("Node Content");
})
})Connect nodes with bezier curve edges:
Edge::new(
(source_node_id, output_index),
(target_node_id, input_index),
&mut selected
)
.distance_per_point(1.0) // Curve sampling distance
.show(ctx, ui)With the layout feature enabled:
use egui_graph::layout;
let positions = layout(
nodes.iter().map(|(id, size)| (*id, size)),
edges.iter().map(|(from, to)| (*from, *to)),
Direction::LeftToRight,
);
view.layout = positions;- Left Click: Select node/edge
- Ctrl + Left Click: Toggle selection
- Shift + Left Click: Clear selection
- Left Drag on Background: Rectangle selection
- Left Drag on Node: Move selected nodes
- Middle Mouse Drag: Pan view
- Scroll Wheel: Zoom in/out
- Delete/Backspace: Remove selected nodes/edges
- Click Output Socket: Start edge creation
- Drag to Input Socket: Preview connection
- Release on Input: Create edge
- ESC: Cancel edge creation
Run the included demo:
cargo run --release --example demoThe demo showcases:
- Multiple node types (labels, buttons, sliders)
- Dynamic node creation and deletion
- Edge creation between nodes
- Automatic layout
- Configuration options
The library follows egui's immediate-mode paradigm while maintaining necessary state for graph interactions. Internal state includes:
- Node sizes
- Selection state for nodes and edges
- Active edge creation
- Socket positions for edge rendering
State is stored in egui's data store and accessed through the widget APIs.