RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Creating HUD AppsLua ↔ UI BridgeGUI Hooks Reference

Reference

UI

Resources

BeamNG Game Engine Lua Cheat SheetGE Developer RecipesMCP Server Setup

// RLS.STUDIOS=true

Premium Mods for BeamNG.drive. Career systems, custom vehicles, and immersive gameplay experiences.

Index

HomeProjectsPatreon

Socials

DiscordPatreon (RLS)Patreon (Vehicles)

© 2026 RLS Studios. All rights reserved.

Modding since 2024

GuidesUI

Lua ↔ UI Bridge

How Lua communicates with the HTML/JavaScript UI layer — events, streams, engine calls, toast messages, and the fade screen system.

The UI bridge connects your Lua code to BeamNG's Chromium-based UI layer. Understanding this bridge is essential for any mod that displays information to the player or responds to UI interactions.


Architecture Overview

┌──────────────┐    guihooks.trigger()     ┌──────────────────┐
│  GE Lua      │ ──────────────────────► │  CEF (Vue/Angular) │
│  (main VM)   │    be:queueHookJS()      │  Browser UI        │
│              │ ◄─────────────────────  │                    │
│              │    bngApi.engineLua()     │                    │
└──────────────┘                          └──────────────────────┘
       ▲                                           ▲
       │ obj:queueGameEngineLua()                  │
       │                                           │
┌──────────────┐    guihooks.trigger()     │
│  VE Lua      │ ──────────────────────► │
│  (per-vehicle)│    obj:queueHookJS()     │
└──────────────┘                          

Lua → UI: Events (guihooks.trigger)

One-shot events. The UI receives them as JavaScript hooks.

-- GE or VE: Send event to UI
guihooks.trigger('MyEventName', data1, data2)

How it works (from guihooks.lua:29-40):

  • Arguments are JSON-encoded via jsonEncodeWorkBuffer
  • Passed to C++ be:queueHookJS() (GE) or obj:queueHookJS() (VE)
  • CEF dispatches to registered JavaScript listeners

UI side (Vue):

// Register a hook listener
bngApi.engineLua('extensions.hook("onSomething")')  // Call Lua from JS

// Listen for Lua events
$scope.$on('MyEventName', function(event, data1, data2) {
  // Handle the event
})

Targeted Events

-- Send to a specific UI window/DSM target
guihooks.triggerClient(targetDsmId, 'EventName', data)

Raw JS Events

-- Send pre-formatted JSON (avoids encoding overhead)
guihooks.triggerRawJS('EventName', '{"key":"value"}')

Lua → UI: Streams (guihooks.queueStream)

High-frequency data channels. More efficient than trigger() for per-frame data.

-- Queue stream data (batched and sent once per frame)
guihooks.queueStream('streamName', dataTable)

How streams work (from guihooks.lua:103-118):

  • Data is cached in a table
  • All cached streams are sent in one batch via guihooks.sendStreams() (called from main.lua's render loop)
  • More efficient than individual triggers for high-frequency data

GE vs VE behavior:

  • VE: Data cached, sent during sendStreams() in the vehicle's graphics step
  • GE: Sets M.updateStreams = true, data cached, sent when main.lua calls guihooks.sendStreams()
-- Stream example: Send vehicle speed every frame
local streamData = {speed = 0}  -- Reuse table!
local function onUpdate(dt)
  streamData.speed = getCurrentSpeed()
  guihooks.queueStream('myModSpeed', streamData)
end

UI → Lua: Engine Calls

JavaScript calls Lua functions via the bngApi:

// Execute arbitrary GE Lua code
bngApi.engineLua('extensions.hook("myHook", ' + bngApi.serializeToLua(data) + ')')

// Call a specific extension function
bngApi.engineLua('mymod_myfeature.doSomething()')

UI Toast Messages

-- Simple message popup (guihooks.lua:127)
guihooks.message("Hello World!", 5, "info", "icon_name")
-- Args: message, ttl (seconds), category, icon

For toast-style notifications:

guihooks.trigger("toastrMsg", {
  type = "info",       -- "info", "warning", "error", "success"
  title = "Title",
  msg = "Message body",
  config = {
    closeButton = true,
    timeOut = 5000,       -- ms, 0 = persistent
    extendedTimeOut = 0
  }
})

UI Graph App

Built-in graph visualization for debugging:

-- guihooks.lua:138-152
-- Each arg: {key, value, scale, unit, renderNegatives, color}
guihooks.graph(
  {"RPM", rpm, 8000, "rpm"},
  {"Throttle", throttle, 1, "%"},
  {"Speed", speed, 200, "km/h"}
)

Loading Screen / Fade Screen

The fade screen is controlled via UI triggers:

-- From ui/fadeScreen.lua
-- Fade to black:
ui_fadeScreen.fadeToBlack(fadeTime, screenData, args)
-- screenData = {image, title, text} shown during black

-- Fade from black:
ui_fadeScreen.fadeFromBlack(fadeTime, args)

-- Full cycle (fade in → pause → fade out):
ui_fadeScreen.fadeSequence(fadeIn, pause, fadeOut, screenData, args)

onScreenFadeState hook receives state changes:

  • 1 = Started fading to black
  • 2 = Fully black (screen is hidden - safe to do visual work like teleporting, swapping vehicles)
  • 3 = Started fading from black
local function onScreenFadeState(state)
  if state == 2 then
    -- Screen is fully black, do visual changes here
    teleportVehicle()
  end
end
M.onScreenFadeState = onScreenFadeState

Performance Notes

  • guihooks.trigger() JSON-encodes all arguments - avoid large tables
  • guihooks.queueStream() is more efficient for per-frame data (batched)
  • Reuse data tables passed to queueStream (see Performance Patterns doc)
  • The tmpTab in guihooks.lua is reused and cleared after each trigger call

See Also

  • GUI Hooks - Full guihooks reference
  • UI Apps - Creating HUD widgets
  • Cross-VM Comms - Full communication patterns
  • Performance - Avoiding per-frame allocation

Creating HUD Apps

How to create UI apps (HUD widgets) for BeamNG.drive — directory structure, AngularJS directives, receiving Lua data, and styling.

GUI Hooks Reference

Complete reference for guihooks — sending events to the UI, toast notifications, streaming data, state changes, and common UI event patterns.

On this page

Architecture OverviewLua → UI: Events (guihooks.trigger)Targeted EventsRaw JS EventsLua → UI: Streams (guihooks.queueStream)UI → Lua: Engine CallsUI Toast MessagesUI Graph AppLoading Screen / Fade ScreenPerformance NotesSee Also