Graph Editor · Guide

// Advanced Editor

Graph Editor

Build a sim-racing dashboard by wiring widgets to live telemetry. Start with a 10-minute hands-on, then dig into the reference for every node.

Part 1 · ~10 min

Quick start

From an empty app to a live RPM bar that reacts to data — no sim required. Seven short steps.

Part 2 · Reference

Node wiki

Every node explained — what it does, its inputs and outputs, and when to reach for it.

Part 1 · ~10 minutes

Quick start

By the end you'll have a bar widget that fills as RPM rises — built, wired, and driven by data. No racing sim required: the editor ships with mock telemetry you can move by hand.

00

Before you start

What you'll build: a horizontal bar whose fill follows the rpm channel, scaled against a max of 5000.

  • No sim needed. SimLogix has a built-in mock telemetry panel with a slider per channel, so you can feed values by hand while you design.
  • Two views, one dashboard. The canvas (top) is the visual preview; the node graph (bottom) is the wiring. You'll use both.
  • Nothing to install. Just the SimLogix desktop app, open on the Editor.
01

Open the editor

  1. Create a dashboard

    On the home Dashboard page, click “+ Nouveau dashboard”. A short wizard asks for a name, a screen resolution (e.g. 1280×720) and a skin. Confirm to create it.

    Dashboard home page with the new-dashboard button
    Fig 1. Home → “+ Nouveau dashboard”.
  2. Open it in the Advanced Editor

    With your dashboard selected, click “Éditeur avancé”. The node editor opens on it.

02

The lay of the land

Spot the areas you'll use. The centre stacks the canvas (visual preview) over the node graph (wiring); tools sit on the left, properties on the right, and the mock telemetry sliders dock by the graph.

The Advanced Editor: tool rail, canvas over node graph, properties panel, mock-telemetry sliders, status bar
Fig 2. The Advanced Editor at a glance.
AreaWhereFor
Tool railfar leftSelect, shapes, and the widget tools you'll use next.
Canvascentre, upperThe visual dashboard — place and arrange widgets.
Node graphcentre, lowerThe wiring behind the visuals.
PropertiesrightEdit the selected widget's look and data.
Mock telemetryby the graphSliders that fake live data so you can test without a sim.
Status barmiddle stripGrid/snap, the telemetry indicator, and zoom.
03

Add a widget

  1. Pick the Bar tool key B

    In the tool rail, choose the Bar widget tool (or press B).

  2. Draw it on the canvas

    Drag a rectangle on the canvas to set the bar's size. A bar appears — empty for now, because nothing feeds it yet. Behind the scenes, it also shows up as a node in the graph below.

    A bar widget drawn on the canvas, half-filled orange
    Fig 3. The bar widget on the canvas.
Widget tools: T text · B bar · I image, plus shapes R rect and O ellipse. V select, H pan.
04

Wire it in the graph

This is the heart of the editor: data flows left → right along wires. The graph already holds an Input node — every channel the game sends — and your new Bar node. You'll connect them.

  1. Connect RPM to the bar's value

    In the graph, drag a wire from the Input node's rpm output to the Bar node's value input. That single connection is the binding.

  2. Give it a max

    Press Tab, add a Number node, set it to 5000, and wire it to the bar's max. Now the fill is RPM scaled from 0 to 5000.

    The graph: Input node wired to the bar's value, a Number constant wired to max
    Fig 4. Input listwidget node via a connection; a Number constant feeds max.
  ┌─────────┐                          ┌──────────────┐
  │  Input  │──── rpm ────────────────▶│ Bar · value  │
  └─────────┘                     ┌───▶│ Bar · max    │
  ┌─────────┐                     │    └──────────────┘
  │ Number  │──── 5000 ───────────┘
  └─────────┘
Prefer not to touch the graph? Select the widget and use the Properties panel's Data tab — its channel picker creates the same wire for you.
05

Make it move

Open the mock telemetry panel and drag the RPM slider. Set it to ~2400 and the bar fills to 2400 of 5000 — a live, data-driven widget. 🎉

RPM connected to bar value, 5000 connected to max, mock telemetry RPM set to 2400, bar filled to 2400 of 5000
Fig 5. Mock RPM = 2400 drives the live bar (0 – 2400 – 5000).
The status-bar dot shows the data source. With a real sim (iRacing, Assetto Corsa) running it turns green and the same wire reads real RPM — no changes needed.
06

Save

Press Ctrl+S. A toast confirms “Dashboard enregistré.” Your dashboard is stored as a .slxd file and reopens exactly as you left it.

Where to go next

  • Add a Text widget wired to gear or speed for a readout.
  • Drop a Remap or Math node between Input and a widget to scale a value, or a Ramp Color to shift color by RPM.
  • Group a sub-network with Ctrl+G into a reusable asset.
  • Browse the node wiki for everything you can wire.
Part 2 · Reference

Node wiki

Every node, grouped by what it does. Each entry shows the node as it looks in the editor — inputs on the left, outputs on the right — plus what it computes and when to use it.

Reading a node

÷Math
in1in2
out

Anatomy

A node has a header (name + an operator glyph where relevant), input sockets down the left edge, and output sockets down the right. Each socket has a type, shown by its colour. Drag from an output to an input to wire them — types must be compatible. A thin top stripe marks the node's category.

in a value the node consumes · out a value it produces · display widgets are sinks (inputs only).

Socket types

Five types, colour-coded everywhere (the same hues the editor uses):

number boolean string color vector any

Categories (the toolbar chips) use their own hues: Data · Compute · Widget · Logic · Doc.

  • number ↔ boolean connect freely (a boolean reads as 1/0; a number is false only when 0).
  • vector never auto-converts to/from number — use Make Vec2 / Split Vec2.
  • A few display inputs (like Text's value) are polymorphic — they accept any type and format it.
  • A wire is rejected if the types are incompatible, if it loops a node to itself, or if it would create a cycle.

Data sources

Input
rpmspeed gear

Input

The single source of live sim data. Outputs one socket per telemetry channel — RPM, speed, gear, throttle, brake and dozens more — grouped into collapsible categories. There's exactly one Input per graph.

out every telemetry channel (+ your math channels)

#Number
out

Const: Number · Bool · String · Color editable

A fixed value you type into the node — a number, a true/false toggle, a text string, or a colour from a picker. Use them as thresholds, labels, fallbacks, and tints (the 5000 max in the quick start is a Number const).

out the constant (number / boolean / string / color)

Make Vec2
xy
out

Vec2: Make · Split · Const vector

Make Vec2 packs two numbers into a vector; Split Vec2 unpacks one back into x/y; Const Vec2 is a fixed vector you edit inline. Vectors carry 2-D things like position or size.

Make x,y → out (vector) · Split in (vector) → x,y · Const → out (vector)

Transform
xy rotationscale…

Transform editable

A position/rotation/scale source. Outputs x, y, rotation, scaleX, scaleY and a normalized anchor (9 presets). Wire it into an asset to place or scale the whole widget.

out x, y, rotation, scaleX, scaleY, anchorX, anchorY (number)

Math & numbers

Several are operator-select: one node with a dropdown that picks the operation. All output a single out (number).

+−×÷Math
in1in2
out

Math operator-select

Arithmetic on two numbers: add, subtract, multiply, divide, modulo, power. Divide/modulo by zero yields 0.

in in1, in2 · out out · glyphs + − × ÷ % ^. Switches to component-wise vec2 mode when a vector is wired.

sincos / sin
in
out

Trig (cos / sin) operator-select

Cosine or sine of an angle in radians.

in in (radians) · out out

maxmin / max
in1in2
out

min / max (extremum) operator-select

The smaller or larger of two numbers.

in in1, in2 · out out

⌊⌋round…
in
out

round / floor / ceil (rounding) operator-select

Round to the nearest integer, or down (floor), or up (ceil).

in in · out out

Clamp
inminmax
out

Clamp

Constrains a value to stay within [min, max].

in in, min, max · out out

|x|Abs / Sqrt
in
out

Abs · Sqrt

Abs gives the magnitude (drops the sign); Sqrt the square root (negatives clamp to 0).

in in · out out

Lerp
abt
out

Lerp

Linear interpolation between a and b by t (clamped 0–1). t=0a, t=1b.

in a, b, t · out out

Remap
infrom…to…
out

Remap

Rescales a value from one range to another — e.g. RPM 0–8000 into 0–1, or a pedal 0–1 into 0–100%.

in in, fromMin, fromMax, toMin, toMax · out out

Color

?If Color
condthenelse
out

If Color

Picks one of two colours by a condition — e.g. green normally, red when a limiter flag is true.

in cond (boolean), then, else (color) · out out (color)

Lerp Color
abt
out

Lerp Color

Blends two colours by t — a smooth two-colour crossfade.

in a, b (color), t (number) · out out (color)

Ramp Color
tstops…
out

Ramp Color editable

Maps a 0–1 input through an editable multi-stop gradient — perfect for RPM shift lights or a temperature scale. Add/move colour stops inline.

in t (0–1) + per-stop offset/color · out out (color). Modes: block, linear, perceptual, smooth, cubic.

Text, time & expressions

Format Time
input
out

Format Time

Turns seconds into a readable time string — lap, sector, race time, or a signed delta.

in input (seconds) · out out (string). Modes: MM:SS.mmm, SS.mmm, H:MM:SS, ±SS.mmm.

ƒExpression
vars…
out

Expression editable

Type a maths formula (e.g. rpm * 0.1 + gear * 5). Each variable you name becomes an input socket automatically.

in one number per variable · out out (number)

Logic & control

&&Logic
in1in2
out

Logic operator-select

Boolean algebra and numeric comparisons in one node: &&, ||, !, and == != < <= > >=. Sockets adapt to the operator (one input for !, two otherwise).

in in1 (, in2) · out out (boolean)

?If
condthenelse
out

If

Numeric branch: outputs then when the condition is true, otherwise else.

in cond (boolean), then, else (number) · out out (number)

Switch
inputfallback
out

Switch editable

Maps a number to a string via a list of cases — e.g. gear 0→"R" 1→"N" 2→"1"…. Emits the fallback if no case matches.

in input (number), fallback (string) · out out (string)

ForEach
count
indexcount

ForEach block

Repeats the nodes inside the block once per iteration — e.g. a row of N shift-light LEDs from one network. Drops a begin node (giving index and count) and an end marker.

in count · out index, count (number, on the begin node)

Display widgets

The sinks: each is a widget on the canvas. They have inputs but no outputs. Any input can be wired (live) or set as a static value in the Properties panel.

TText
valuefillColor

Text

A text label. Its value is polymorphic — wire a number, string, etc., and format it (number, time) in Properties.

in value (any), fillColor (color), effects

Bar
valuemaxfillColor

Bar

A progress/level bar (the one you built in Part 1). Fill scales value against min/max.

in value, min, max (number), fillColor (color), effects

Rect
fillColorstroke…

Rect

A rectangle — solid or with a linear gradient and strokes. Great as a backdrop, panel, or status block.

in fillColor or gradient stops, stroke width/color, effects

Ellipse
effects

Ellipse

A circle or ellipse. Static-only for now (set its look in Properties).

in effects

Image
opacity

Image

An image — a logo, car silhouette, or custom gauge face. Source and scale set in Properties.

in opacity (number), effects

Subgraphs & assets

Asset
inputs…x, y…
outputs…

Asset instance

A reusable widget — a packaged sub-network with typed inputs and outputs (like a function or component). Make one by selecting nodes and pressing Ctrl+G, or drop a built-in from +Widget. Assets can nest, and each instance can override inputs and styling.

in the asset's inputs + transform (x, y, rotation, scale, anchor) · out the asset's outputs

In / Out
params…

Subgraph Inputs & Outputs

Found inside an asset's body: Inputs exposes the asset's parameters as outputs to wire from; Outputs collects its results. Created automatically — you don't add them from the menu.

Inputs → out per parameter · Outputs ← in per result

Annotations

Note / Frame

Note · Frame

Documentation, not computation. A Note is a free-floating text label; a Frame is a titled box that groups nodes and moves them together. Neither affects the result — they keep a graph tidy.

no inputs · no outputs · visual only

Appendix · For contributors

Under the hood

A brief look at how the graph is stored and evaluated. Skip this if you're just building dashboards.

Data model & evaluation

The body / layout split

A graph is two concentric parts. The body is the eval contract — nodes and wires, no visuals. The layout holds positions, notes and frames. Because positions live only in layout, moving a node never changes the body — evaluation and asset signatures are drag-stable.

Graph = {
  body:   { nodes: StructuralNode[], wires: Wire[] },           // eval contract — no visuals
  layout: { nodes: Record<id, {x,y,…}>, notes, frames },        // visual state only
}

How it evaluates

Each engine tick, evalGraphCore reads the body only and: (1) topologically sorts the nodes (a cycle throws — which is why cyclic wires are rejected at draw time); (2) handles any ForEach block by partitioning into pre / loop / post zones and running the loop once per iteration; (3) evaluates each node via a tiny dispatcher into the registry; (4) collects the resolved inputs of every display node; (5) re-orders by document order for correct stacking. The result feeds the renderer.

The registry — adding a node

Every node kind is one NodeDef entry colocating its kind, label, category, Zod schema, build() factory, eval(), and socket-type resolver. The goal: adding a node = one entry in registry/primitives.ts or registry/non-primitives.ts (+ a React component), nothing else.

Code lives in software/simlogix/ui/src/features/advanced-editor/graph/. The folder's own summary.md tracks change history and links the design specs.