Docs
FX Pro dash format (FormatVersion 2)
A dash is one JSON file: an 800x480 page of elements the plugin draws on the FX Pro's screen with the screen's own
commands (USB mode, usb-mode.md). Files live in SimHub\PluginsData\Common\FXProRpmSync\Dashes\*.json;
the designer (dash-designer.md), fxdash and the SimHub importer write them, and people or agents can
write them by hand. Code: Usb/DashModel.cs (model), Usb/DashRenderer.cs (drawing and checks).
The machine-readable version of this page: fxdash schema or GET /api/schema.
The screen
- 800 x 480 pixels, origin top left, 16-bit colour (RGB565: colours are rounded to 5/6/5 bits).
- Nothing is a picture: shapes become
fillrectangles, text is drawn by the screen in its own fonts (by id), and images are cut into rectangles of a few colours. Flat colours draw fastest. - The wheel pads the whole dash (USB mode setting, default 10 px left, 20 px top): keep the layout within
(800 - left) x (480 - top), i.e. 790 x 460 by default.
checkwith the padding reports anything pushed off. - When the dash starts, its static layer goes out at 25 KB/s (
check'scost.StaticSeconds, ~0.6 s for the built-in Mustang). After that only what changes is redrawn (~1-2 KB/s).
The file
{
"FormatVersion": 2,
"Id": "my-dash", // file name when saved; unique
"Name": "My dash", // shown in the dash list
"Author": "", "Description": "",
"Elements": [ ... ], // drawn in order: later ones on top
"Images": { "logo@120x40": "<base64 PNG>" }, // only for image elements
"Source": "SimHub dash ...", // set by the importer
"ScriptsFolder": "..." // JavaScript helpers for js: bindings (imports)
}
Elements
Every element: Type, Name (shown in messages and the designer), X, Y, W, H (pixels), and optionally
Visible, PreviewVisible, ColorBind, ColorStops, Opacity (0-100, shapes).
| Type | What | Fields |
|---|---|---|
rect |
filled rectangle | Color |
ellipse |
ellipse, or a ring | Color (whole ellipse, or the rim when Border > 0), Fill (inside, optional), Border |
box |
rounded frame | Color (border), Fill (inside, optional), Border, Radius |
gradient |
linear gradient | Colors (2+ stops), Angle (90 = top to bottom, 0 = left to right), Radius, Border + Color |
image |
picture | Image (key in Images), MaxColors (2-64, default 8; fewer = faster) |
label |
fixed text, no background | Text, Font, Color, Align (left / center / right) |
value |
text from data | Bind, Format, Scale, Empty, Samples, PreviewText, Font, Color, Align, PositiveColor / NegativeColor, Background |
bar |
gauge fill | Bind, Min, Max (may be below Min), Orientation (horizontal / vertical), Reverse, Color (fill), Fill (empty part, optional) |
deltabar |
segments filling from the centre | Bind, Segments (per side), SegmentX (left edges, 2 x Segments) or Pitch, SegmentWidth, Range (value of a full half), PositiveColor (left half, value > 0), NegativeColor (right half), SegmentColor |
popup |
box shown for Duration s when a watched value changes |
Watch [{Bind, Label, Color, Format}], Font (label), ValueFont, Color (text), Radius |
Colours: "#RRGGBB", "#AARRGGBB" (alpha blends shapes over what's under them) or colour names.
Text: fonts and boxes
Fontis a screen font id:fxdash fonts/GET /api/fontslists all 128 with height and characters. A font's height must fit the box (H), and every text it shows must fit the width (W): text wider than its box wraps onto a line the screen doesn't show, so it just disappears.- Real advance widths are in
FontMetrics.cs; many of Simagic's fonts are wide (in the "S" fonts a digit is as wide as the font is tall). Narrow, readable families: 963 (ids 96-101; 101 = 32 px, 98 = 40, 100 = 50), isf23 (92-95), 992 (69-72). Gear fonts (0-9 D N P Ronly): 117 (119 px), 102 (128), 38 (104). fxdash suggest-font W H TEXT/GET /api/fonts/suggestpicks the tallest font whose TEXT fits a W x H box.- Values: give
Samples(the widest texts it can show, e.g.["8:88.888"]) socheckcan verify them;Emptyis shown when there's no data;PreviewTextis what previews show. - Vertical alignment is always centred in the box.
- Value backgrounds are automatic: the one colour under the box, or, over an image/gradient, the area is redrawn before
each new text (slower:
checkwarns).Backgroundforces a colour.
Data: bindings and formats
Bind, ColorBind, Visible and pop-up watches take a binding:
- a key:
speed,gear,gearText,rpm,maxRpm,rpmPercent,throttle,brake,clutch,currentLapTime,lastLapTime,bestLapTime(s),delta(s to session best, + = slower),predictedLap,position,lap,completedLaps,fuel,fuelPercent,fuelLastLap,fuelThisLap,fuelRemainingLaps,virtualEnergy(LMU, %),brakeBias,absLevel,tcLevel,tcCut,tcSlip(LMU),engineMap,sessionTypeName,waterTemp,oilTemp,absActive,tcActive,pitLimiter,gameRunning(full list with descriptions:fxdash bindings); "prop:<SimHub property>", e.g."prop:DataCorePlugin.GameRawData.PlayerNativeTelemetry.mVirtualEnergy";- a SimHub formula:
"ncalc:<NCalc>"(e.g."ncalc:[DataCorePlugin.GameData.NewData.Rpms] > 7000") or"js:<JavaScript>"(a function body withreturn, SimHub's$prop('...')available). Evaluated by SimHub's own engine while SimHub runs. Previews (preview mode) showPreviewText/ followPreviewVisibleinstead.
Demo mode (the Demo button, the designer's Demo lap and Show on wheel without a game, fxdash render --mode demo)
fills every binding from the simulated lap: built-in keys directly; prop:, ncalc: and js: bindings are evaluated
with the engines SimHub ships (NCalc, Jint) over simulated SimHub properties (the demo lap's speed, laps, fuel... plus
tyre/brake temperatures, pressures, wear, settings, flags and more guessed from the property's name) and SimHub's
formula functions (isnull, format, changed, toshorttime, driver...), loading the dash's
ScriptsFolder scripts. A binding that still can't be worked out (an unknown plugin's property, say) shows its
PreviewText, with its numbers moving a little every few seconds; such a condition follows PreviewVisible.
So PreviewText is worth setting to a typical value.
Formats: any .NET number format ("0", "0.0", "0.00"), int, laptime (m:ss.fff from seconds), time:<fmt>
(TimeSpan format from seconds, e.g. time:mm\:ss\.fff), gear (R / N / number), delta (+0.00 / -0.00), text.
Scale multiplies before formatting.
Conditions and data colours
Visible: a binding or a list; the element shows while all are true (a number other than 0,true, a text other than "", "0", "false"). Hiding it redraws what was under it.PreviewVisible:false= hidden in previews where the condition isn't evaluated (SimHub formulas), and in the demo where it can't be. The importer sets it for pop-ups and warnings.ColorBind: a binding giving a colour ("#FF0000", a colour name) or a number mapped throughColorStops[{"Value": 0, "Color": "#00FF00"}, {"Value": 100, "Color": "#FF0000"}](blended between). ReplacesColorfor text, rects and bars, the fill for boxes/ellipses with aFill.
Checks
fxdash check DASH.json --pad 10,20 / POST /api/check?left=10&top=20 returns issues (level error = the screen
will show it wrong, warning = costly or doubtful) and cost (StaticSeconds, StaticFills, values on busy
backgrounds). Errors: text wider/taller than its box, missing glyphs, unknown types/fonts/images, text off the screen.
Warnings: overlapping always-shown text, values without Samples, unknown data keys, busy value backgrounds, slow
static layers.
Example
{
"FormatVersion": 2, "Id": "minimal", "Name": "Minimal",
"Elements": [
{ "Type": "box", "Name": "frame", "X": 250, "Y": 40, "W": 290, "H": 250, "Color": "#428AED", "Border": 4, "Radius": 16 },
{ "Type": "value", "Name": "gear", "Bind": "gear", "Format": "gear", "X": 300, "Y": 60, "W": 190, "H": 125, "Font": 117,
"Color": "#FFFFFF", "Align": "center", "Samples": ["N", "R", "8"], "Empty": "N" },
{ "Type": "value", "Name": "speed", "Bind": "speed", "Format": "0", "X": 300, "Y": 200, "W": 190, "H": 50, "Font": 100,
"Color": "#D3D3D3", "Align": "center", "Samples": ["388"] },
{ "Type": "bar", "Name": "revs", "Bind": "rpmPercent", "Min": 60, "Max": 100, "X": 20, "Y": 320, "W": 750, "H": 30,
"Color": "#00FF40", "Fill": "#202020",
"ColorBind": "rpmPercent", "ColorStops": [{ "Value": 80, "Color": "#00FF40" }, { "Value": 95, "Color": "#FF0020" }] },
{ "Type": "label", "Name": "pit", "Text": "PIT LIMITER", "X": 280, "Y": 380, "W": 230, "H": 40, "Font": 98,
"Color": "#0040FF", "Align": "center", "Visible": "pitLimiter" }
]
}