Unaffiliated

Home Documentation & Help
Steamworks Documentation
In-Game Actions File

Overview


Developers must supply an In-Game Actions (IGA) file that defines the actions, action sets, and basic structure of their game's input configuration. This article describes the overall structure of this file and provides several concrete examples from various games.

Example Files


Generating an IGA file for any game


If you save a configuration for any game on Steam as a "local" configuration, you can then find a corresponding file in:
[SteamDirectory]\UserData\[youruserid]\241100\remote\controller_config\[appid]\[savename].vdf

Here's an example of where my local configurations for Defender's Quest are stored on a typical Windows 10 machine:

whereisvgf.png

Note that these files are not exact replicas of the master IGA file uploaded by the developer, but you can get an idea for the original structure by looking at the "actions" and "localization" blocks, which are drawn directly from the master file.

Here's a download link for the #library_controllersavedefaulttitle_0.vdf file shown in the above screenshot, you might find it useful to compare that to the master Defender's Quest IGA.

IGA Format


The IGA file takes the form of a VDF document, which is Valve's own data format for creating structured object data with key/value string pairs.

Skeleton


The basic structure of the file is a wrapper object with the name "In Game Actions", and two sub objects, named "actions", and "localization", respectively:

"In Game Actions" { "actions" { } "localization" { } }

Action Sets

Let's zoom into the "actions" object. This object will contain your action sets. The structure of an "actions" object looks like this:
"actions" { "ActionSetNameGoesHere" { "title" "#TitleGoesHere" "StickPadGyro" { } "AnalogTrigger" { } "Button" { } } }

The strings "ActionSetNameGoesHere" and "#TitleGoesHere" are the only strings in the above example the user should replace, the rest are reserved key words.

The value you replace "ActionSetNameGoesHere" with will be the name of the action set that you use in the Steam Controller API. And the value you replace "#TitleGoesHere" with will be the localization token you use in the "localization" section later in the file. Note that the # sign is required here.

Each action set should have a unique string name, and you add more just by creating more objects within the scope of the "actions" container object. No commas or square brackets are necessary -- this is VDF, not JSON.

There are three possible sub-objects for each action set object. They are "StickPadGyro", "AnalogTrigger", and "Button". These are the only possible objects you can define, and they are the containers that will house your individual action definitions. You do not have to provide all three categories, however.

This structure is perfectly valid, for instance:
"actions" { "ActionSetName1" { "title" "#Title1" "AnalogTrigger" { } "Button" { } } "ActionSetName2" { "title" "#Title2" "StickPadGyro" { } } "ActionSetName3" { "title" "#Title3" "Button" { } } }

StickPadGyro

This action set block is for analog actions that will have up to two axes of motion, the sort of thing you might want to bind to a joystick, a touchpad, or a gyroscope. Also, anything you might want to control with a mouse or anything else like that should go in here.

AnalogTrigger

This action set block is for analog actions that will have only one axis of motion, the sort of thing you might want to bind to an analog trigger.

Button

This action set block is for purely digital actions, which only report an on/off state. Despite the name of this block being "button," digital actions can be bound to just about any physical inputs -- including ones originally designed to output analog data (such as joysticks, touchpads, etc).

Actions


An IGA file won't actually do anything until it's got some actions defined, so let's add some!

StickPadGyro Actions

Let's start by adding some StickPadGyro (2-axis analog) actions. How about something to move the character around -- we'll call it "Move", and something to control the camera -- we'll call it "Camera."

"actions" { "FPSControls" { "title" "#Set_FPSControls" "StickPadGyro" { "Move" { "title" "#Action_Move" "input_mode" "joystick_move" } "Camera" { "title" "#Action_Camera" "input_mode" "absolute_mouse" } } } }

As you can see the abstract structure for a StickPadGyro action is:
"ActionNameHere" { "title" "#ActionTitleHere" "input_mode" "<analog_mode>" }

The only user-editable values in this structure are the ones I've marked "ActionNameHere", "#ActionTitleHere", and "<analog_mode>". Respectively, they correspond to the action's string name for use in the Steam Controller API, the localization key for use in this file's localization section, respectively, and the Input Source Mode that governs how the analog data is processed and interpreted.

The "input_mode" property has two possible values for StickPadGyro actions:

  • "joystick_move"
  • "absolute_mouse"

You should use "joystick_move" for an action whose values are interpreted as a joystick (constant deflection from a central point), and you should use "absolute_mouse" for a more flexible general purpose analog action. When in doubt, use "absolute_mouse".

"joystick_move" vs. "absolute_mouse"

We can’t stress enough that when creating a camera input for your first/third person game or anything cursor driven, you should always use the "absolute_mouse" type and react to deltas as if it’s a mouse.

The API will automagically do the right thing here for stick based input, so you'll still get a tunable stick input if your camera is applied to an analog stick (PS4/Xbox style) with full dead zones/response curves/etc. that you can specify in your default configuration. This same input will then work across joysticks, track pads, or motion control gyros (Steam Controller/PS4) as well as future support for mice.

You should not use the "joystick_move" based input method for your camera, as mapping the opposite direction to get useful 1:1 data for pad/gyro/mouse/motion controls isn't possible.

This also applies to cursor based input - "absolute_mouse" as a cursor will work just fine on stick based inputs, so you don't have to worry about creating your own stick based cursor, should you need one.

You can optionally send low-level mouse events along with your analog data. Your game will not be able to distinguish these mouse events from those generated by your operating system. You do this by adding the value "os_mouse" and assign it a value of 1.

Here's an example:
"StickPadGyro" { "Mouse" { "title" "#Action_Mouse" "input_mode" "absolute_mouse" "os_mouse" "1" } }



AnalogTrigger Actions

(coming soon)

Button Actions

Button actions are the simplest to define. You simply add two strings on the same line -- the name of the action, and the localization key. Like this:

"Button" { "digital_action_1_name_here" "#DigitalAction1TitleHere" "digital_action_2_name_here" "#DigitalAction2TitleHere" }

If necessary, you can define a native low-level input hardware event (like a native mouse click) that fires alongside the action. This is useful in some edge cases where your game relies on e.g. a finicky input stack seven layers deep that never quite treats simulated mouse events from your application layer the same as those directly generated by the operating system.

"Button" { "simple_click" "#simple_click" "fancy_click" "#fancy_click, mouse_button LEFT" }

This causes the game to emit a true, operating-system-level left mouse button event every time the "fancy_click" action is fired.

Warning!

You should never use this trick as a crutch for forcing specific fixed input bindings for your actions. That defeats the entire purpose of the "actions, not inputs" paradigm and giving the user full control over their configuration. If you find yourself using this feature for more than just fixing a few rare edge cases, you're probably overusing it.

Localization


The master IGA file should include a localization section alongside the action set definitions. The individual child objects of the localization object will be any one of the language strings that Steam supports. Make sure you include at least one block that contains English action titles.

"localization" { "english" { "move" "Move" "camera" "Camera" } }

Note that the names of the properties should correspond to the localization keys you specified in the earlier sections, except without the "#" character.

To add additional languages, simply add more language blocks with localized text for each entry:

"localization" { "english" { "move" "Move" "camera" "Camera" } "spanish" { "move" "Mover" "camera" "Cámara" } "norwegian" { "move" "Bevege" "camera" "Kamera" } }

The full list of languages supported by Steam is:

  • brazilian
  • bulgarian
  • czech
  • danish
  • dutch
  • english
  • finnish
  • french
  • german
  • greek
  • hungarian
  • italian
  • japanese
  • koreana
  • korean
  • norwegian
  • polish
  • portuguese
  • romanian
  • russian
  • schinese
  • spanish
  • swedish
  • tchinese
  • thai
  • turkish
  • ukrainian

How Steam uses your IGA file


The master IGA file you create will only ever be during development (but it should still be saved, maintained, and stored in your version control, etc). When you create an official input configuration for your game during development, the Steam client uses your master IGA file to generate a starting template.