The Editor Takes Shape

Am I now a UX designer????!!!!

Probably not. But the editor is starting to feel like a real thing.

Three renderers in a trench coat

The editor runs three rendering systems in one window:

  1. Vello renders the node canvas (nodes, wires, shapes)
  2. egui renders the UI panels (browser, inspector, menus)
  3. wgpu composites them together (blit + egui on top)

Every frame: evaluate the graph → render the output → render the canvas → blit to surface → paint egui on top. The egui pass uses LoadOp::Load so the canvas content underneath is preserved. It sounds complicated but it’s really just layers.

‘Editor’

The canvas

The canvas is an infinite pan/zoom surface. Middle-click drag to pan, scroll to zoom. All graph-space content (nodes, wires) lives inside a transform:

PushTransform(zoom * pan_matrix)
  ...all the nodes and wires...
PopTransform

The background grid stays in screen space. Hit testing converts screen coordinates to canvas space: (screen_pos - offset) / zoom. Simple, and it means zoom is just a number, no re-layout needed.

Nodes as draw commands

Each node renders as a stack of shapes:

  1. Body (rounded rect, darker on hover)
  2. Border (purple when selected)
  3. Family accent stripe (3px colored bar on the left, different colors for texture, math, I/O, etc.)
  4. Name text
  5. Pin circles (colored by type)

I cache the draw commands per node. If nothing about a node changed since last frame, I reuse the cached commands. Only hovered/selected nodes get redrawn.

Seven node families, seven colors

Nodes are color-coded by category:

  • Texture nodes: purple
  • Channel/math: green
  • Geometry: blue
  • Logic: orange
  • Material: yellow
  • Component: grey
  • GPU: pink

You can instantly see what a patch is doing by the colors. A wall of purple? That’s image processing. Mix of green and purple? Data driving visuals.

Pin tooltips and wire highlights

ok, ok… I put the text in!

Hover a pin and you get its name and type. But the cool part is during wire dragging, when you’re pulling a wire from an output pin, every compatible input pin lights up. Incompatible pins dim. You instantly see where your wire can go.

The compatibility check uses the same PinType::can_coerce_to() logic as the graph engine. If the evaluator would accept the connection, the pin lights up.

The browser and inspector

Left panel: node browser. Groups nodes by category, click to spawn at canvas center. Simple.

Right panel: inspector. Select a node and see all its input pins with appropriate widgets, sliders for numbers, checkboxes for bools, color pickers for colors, text fields for strings. Change a value and the graph re-evaluates next frame.

Both panels are egui. Nothing fancy. They work.

What I learned

Building a visual programming editor is really about feel. Does the pan feel smooth? Does the zoom center on the cursor? Does the wire preview follow your mouse without lag? These are tiny things that nobody notices when they’re right and everybody notices when they’re wrong.

I’m not done, there’s no undo yet, no search, and the node placement is manual. But you can build a patch, connect wires, and see output. That’s a milestone.

← Back to blog