# egui_graph
A general-purpose node graph widget for [egui](https://github.com/emilk/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](https://github.com/nannou-org/gantz). For a more
sophisticated example of what can be built with egui_graph, check out
[gantz](https://nannou-org.github.io/gantz).
## Key Design Philosophy
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.
## Features
- **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-rs` crate
- **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
## Quick Start
```rust
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.
## Core Components
### Graph Widget
The main widget that contains all nodes and edges:
```rust
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
Nodes are containers with input/output sockets:
```rust
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");
})
})
```
### Edges
Connect nodes with bezier curve edges:
```rust
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)
```
### Automatic Layout
With the `layout` feature enabled:
```rust
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;
```
## Controls
### Mouse Controls
- **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
### Keyboard Controls
- **Delete/Backspace**: Remove selected nodes/edges
### Socket Interaction
- **Click Output Socket**: Start edge creation
- **Drag to Input Socket**: Preview connection
- **Release on Input**: Create edge
- **ESC**: Cancel edge creation
## Examples
Run the included demo:
```bash
cargo run --release --example demo
```
The demo showcases:
- Multiple node types (labels, buttons, sliders)
- Dynamic node creation and deletion
- Edge creation between nodes
- Automatic layout
- Configuration options
## Architecture
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.