Action Maps

Overview

Action maps are assentially groups of bindings, with a name.

Their main purpose is to define the priorities of their bindings, and also to enable/disable all of them easily.

Example

Let’s take the replay functionality as an example:

All replay-related bindings are grouped into the same action map, named "ReplayPlaybackActionMap".

This action map is activated while you open a replay.

It can also be given higher priority than the regular driving controls, so that the right arrow key won’t try to steer the vehicle, but will instead advance the replay 10 seconds forward.

Actionmap execution order

When an Event is generated, BeamNG.drive takes the first action map, and checks if it contains relevant bindings to execute:

  • If there’s no bindings associated to this Event, it will take the next action map in order, and check again (until there’s no more action maps left to check).
  • If there is any relevant binding, it/they will be executed, and no more action maps will be checked after that*.

(* unless the trap flag has been set)

Hierarchy

Action Maps can be active or inactive, and there’s a list for each.

You can visualize both lists at any time, by running this command in the GE-Lua console:

dump(ActionMap:getList())

List of active action maps

These are the default action maps that are active right after starting the game, and their order;

  1. GlobalActionMap
  2. MenuActionMap
  3. GuiActionMap
  4. <– activation point
  5. VehicleSpecificActionMap
  6. VehicleCommonActionMap
  7. NormalActionMap

The action maps on top are prioritized: they get a chance to process bindings before those at the bottom.

List of inactive action maps

There’s a second one that lists all inactive action maps.

Inactive maps are never taken into account, the end-user is unable to use any of their bindings, and therefore their ordering does not matter.

At the time of writing this article, the inactive list typically contains:

  • FlexmeshDebugActionMap
  • ReplayPlaybackActionMap
  • ExplorationGeneralActionMap

Custom Action Maps

Additional action maps can be added by mods, by merely choosing a new actionMap field name in the .json action files.

That name + the suffix "ActionMap" will be used as its scenetree identifier. For example, using 'actionMap':'FunStuff' will lead to the creation of an action map accessible via scenetree.findObject('FunStuffActionMap').

All additional actionMaps will be inactive by default.

In order for the new actionMaps to be usable, they must be activated first (and later deactivated, if/when you’re finished with them).

Activating (pushing) and Deactivating (popping) action maps

Activating an action map means moving it from the inactive list to the active list.

In other words, the action map is pushed into, or popped out of, the active list.

ActionMaps can be activated at any time, by running the following GE-Lua code:

local actionMapName = "MyActionMap"
scenetree.findObject(actionMapName):push()

In order to deactivate it later, use this;

local actionMapName = "MyActionMap"
scenetree.findObject(actionMapName):pop()

This will move the action map back to the inactive list.

ActionMaps are activated (pushed) roughly right below the GuiActionMap (see List of active action maps).

Therefore, their priority is lower than the gui/menu/global action maps, and higher than previously activated action maps.

In practice, this means that a mod can never override, for example, the ALT+F4 binding that exits the game. This happens by design.

Enabling and Disabling action maps

This is shown as enabled = true or enabled = false when displaying the action map hierarchy.

It’s a rarely used feature, but documented here for completeness. It allows to deactivate an action map without losing its position (priority) in the List of active action maps (without moving the action map from the active to the inactive list).

The main purpose is allowing to disable all Menu action map bindings while the menus are closed (and re-enabling them if the end-user starts navigating the menus), while maintaining the proper priority of its bindings.

Trapping handled events

This boolean flag can be set for each action map. Its default value is true.

It is shown as trapHandledEvents = true or trapHandledEvents = false when displaying the action map hierarchy.

It’s another rarely used feature, again documented here for completeness.

If this flag is false, then the Actionmap execution order behaviour is altered: the lower-priority action maps will be checked even after a binding has been found in the current action map.

E.g. if the first half of the actionmaps stack have this flag set to false, and the second half have this flag set to true, then all bindings in the first half will be processed. After that, the first actionmap with a matching binding will be processed, and the rest of actionmaps won’t be given the chance (since the event has just been trapped by this last matching actionmap).