Extending the UI
Available via from railroader import ui in Main.rl.
ui provides APIs for extending built-in UI panels (the car inspector’s tabs and customization section) with custom content, plus APIs for custom windows, console commands, and car customization editors. See also:
- UIPanelBuilder — the builder type used to populate extensions and windows, plus
ConfigurableElement - Windows —
createWindow()/getWindow() - Commands —
registerCommand() - Style Properties —
registerStyleProperty()
Extending the UI
Section titled “Extending the UI”extensionPoint string Extension point identifier, e.g. "carInspector.equipment" Registers a UI section at an extension point, returning a builder to configure it. Returns null (and logs a warning) if extensionPoint is empty or isn’t one of the known extension points.
ui.extend("carInspector.equipment.customize") .id("my-customization") .matching({"identifier": "rr/my-car"}) .priority(100) .with(buildUI)
func buildUI(builder, car) { builder.section("My Section") builder.rebuildOnPropertyChange(car.properties, "customize.option") builder.fieldToggle("Enable Option", () => car.properties["customize.option"] ?? false, (value) => { car.properties["customize.option"] = value } )}Extension Points
Section titled “Extension Points”| Extension Point | Context | Description |
|---|---|---|
carInspector.equipment | Car | Equipment tab of the car inspector |
carInspector.equipment.customize | Car | Customization section (paint, options) of the car inspector’s equipment tab |
carInspector.operations | Car | Operations tab of the car inspector |
companyWindow.main | — | Reserved for a future company window integration; accepted by ui.extend() but not yet invoked anywhere in-game |
Builder Methods
Section titled “Builder Methods”The object returned by ui.extend(). Every method except .with() returns the same builder, so calls chain together.
id string Unique identifier for this extension Sets the extension’s ID. Re-registering the same ID on the same extension point replaces the previous registration. Defaults to the calling asset pack’s identifier if never called.
criteria dict String key/value pairs to match against the extension point's context Restricts this extension to contexts matching all given key/value pairs. See Matching Keys. Call it more than once to match any of several sets: the extension applies when every pair in at least one call matches. Omitting this call, or passing an empty dictionary, makes the extension apply to every context.
ui.extend("carInspector.equipment.customize") .id("my-customization") .matching({"identifier": "mymod/boxcar-40ft"}) .matching({"identifier": "mymod/boxcar-50ft"}) .with(buildUI)Throws if criteria isn’t a dictionary, or holds a non-string key or value.
priority int Ordering value; lower values are invoked first Sets the extension’s ordering among other extensions on the same extension point. Defaults to 0.
builderFunc (UIPanelBuilder, Car) => void Called as (builder, car) for car inspector extension points, or (builder) (no car argument) for other extension points Registers the extension with the given builder function. Ends the chain. See UIPanelBuilder for what builder can do.
Matching Keys
Section titled “Matching Keys”For car inspector extension points, .matching() criteria are checked against:
| Key | Description |
|---|---|
identifier | Definition identifier (e.g. "rr/boxcar-40ft") |
carType | AAR car type code (e.g. "XM") |
Omitting .matching() makes the extension apply to every context.
© 2026 Giraffe Lab LLC. All rights reserved.