This document describes the structure and semantics of the configuration system used to map game controllers (e.g., joysticks, gamepads) to controls in Train Sim World using UE4SS. It is designed to be flexible, extensible, and friendly to both analog and digital input devices.
Each control on a game controller can be assigned an action. Assignments describe when and how the actions are triggered based on the input. Actions describe what happens when triggered.
All assignments conform to a top-level enum ControllerProfileControlAssignment, which contains the following variants:
MomentaryToggleLinearDirectControlSyncControlApiControlEach assignment type has a specific use case and behavior, described below.
Used for buttons that act while held.
{
"type": "momentary",
"threshold": 0.5,
"action_activate": { ... },
"action_deactivate": { ... }
}
threshold.threshold. (optional - by default if the action_activate defines a keystroke to be held; it will be released automatically when releasing the gamepad control)Used for toggle switches that alternate between two states.
{
"type": "toggle",
"threshold": 0.5,
"action_activate": { ... },
"action_deactivate": { ... }
}
action_activate.action_deactivate.Used for analog levers or sliders with multiple threshold points.
{
"type": "linear",
"thresholds": [
{ "threshold": 0.2, "action_activate": { ... }, "action_deactivate": { ... } },
{ "threshold": 0.7, "action_activate": { ... }, "action_deactivate": { ... } }
]
}
Maps an analog controller input to a continuous value in-game.
{
"type": "direct_control",
"controls": "Throttle1",
"input_value": {
"min": 0.0,
"max": 1.0,
"invert": true
},
"notify": true
}
step or steps to quantize values.{SIDE} placeholder to automatically select the correct side of the cab. This is specifically for controls named Throttle_F or Throttle_B where the F and B mark the side of the cab.| Name | Description |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| hold | Whether to continuously hold this value. Useful for levers which automatically reset. (such as the Tube Deadman or some brake levers) |
| notify | Whether to enable the in-game notifier when changing values to display the current value (defaults to true but can be explicitly disabled) |
A safer alternative to DirectControl for unstable locos.
{
"type": "sync_control",
"identifier": "Reverser1",
"input_value": {
"min": -1.0,
"max": 1.0,
"steps": [-1.0, 0.0, 1.0]
},
"action_increase": { "keys": "PageUp" },
"action_decrease": { "keys": "PageDown" }
}
Maps an analog controller input to a continuous value in-game using the HTTP API.
{
"type": "api_control",
"controls": "Throttle1",
"input_value": {
"min": 0.0,
"max": 1.0,
"invert": true
}
}
step or steps to quantize values.Each assignment triggers an action when activated (and optionally when deactivated). Actions can be:
{
"keys": "W",
"press_time": 0.1,
"wait_time": 0.05
}
{
"controls": "Throttle1",
"value": 0.5,
"hold": false,
"relative": false
}
{
"controls": "Throttle1",
"api_value": 0.5
}
Used by DirectControl, SyncControl and ApiControl to map axis input to control values.
{
"min": -1.0,
"max": 1.0,
"step": 0.1,
"steps": [0.0, 0.2, null, 0.5, null, 1.0],
"invert": true
}
min / max: Range of values.step: Optional increment size.steps: Optional list of discrete valid values. Can be used with null values to create zones of free motion between detents.invert: Whether to reverse the axis.It is also possible to only execute assignments depending on one or more conditions. This can be used to create multi-key assignments. (eg: the action of a button changes depending on the position of a lever).
This can be added to any assignment using the conditions key:
{
"type": "momentary",
"conditions": [
{
"control": "mylever",
"operator": "gte",
"value": 0.5
}
]
}
In the above example, the assignment will only execute if mylever exceeds 0.5. At this time the supported operators are gte, lte, gt and lt.
DirectControl for stable, high-resolution mappings, especially lever controls.ApiControl if you are unable to or do not want to use DirectControl (ApiControl is less flexible and is less performant, but still provides a near direct control option)SyncControl if you want a direct control like experience but want to use keybindings. (this may be helpful since using keybinds trigger the in-game value notifications)Linear for fine-grained, manually configured lever behavior.Momentary for temporary actions like horn or bell.Toggle for switches with two states.{
"type": "momentary",
"threshold": 0.5,
"action_activate": {
"keys": "H"
},
"action_deactivate": {
"keys": "Shift+H"
}
}
Happy simming! ๐