Angular Overlay Pattern (Mod UI)
How to create a full-screen overlay UI (splash screen, popup, modal) from a mod that renders on top of everything in BeamNG's CEF UI.
How to create a full-screen overlay UI (splash screen, popup, modal) from a mod that renders on top of everything in BeamNG's CEF UI.
See Also
- Communication / UI Bridge: How Lua↔UI data flows
- Phone UI: Phone app UI reference
The Problem
BeamNG's UI is Angular-based (AngularJS 1.x). Mod UIs loaded via ng-include or route views are confined to their container's z-order. If you need a UI that overlays on top of everything (like a splash screen or a binding popup), you can't just add a template to an existing view.
The Pattern: Angular .run() Block Injection
Use an angular.module(...).run(...) block to inject a container directly into document.body. This container uses ng-controller and ng-include to bootstrap your overlay template.
JavaScript (e.g. guide.js)
angular.module('beamng.apps')
.run(['$rootScope', '$compile', function($rootScope, $compile) {
// Create a container div that sits on top of everything
var container = angular.element(
'<div id="guide-overlay-container" ' +
'ng-controller="GuideController" ' +
'ng-include="\'modules/guide/guide.html\'">' +
'</div>'
)
// Append to document.body (top-level, above all other UI)
angular.element(document.body).append(container)
// Compile against root scope so Angular processes directives
$compile(container)($rootScope.$new())
}])
.controller('GuideController', ['$scope', function($scope) {
// Your controller logic here
$scope.visible = false
$scope.show = function() { $scope.visible = true }
$scope.hide = function() { $scope.visible = false }
// Listen for Lua → UI calls
$scope.$on('GuideShow', function(event, data) {
$scope.$evalAsync(function() {
$scope.visible = true
$scope.data = data
})
})
}])HTML Template (e.g. guide.html)
<div ng-if="visible" class="guide-overlay">
<div class="guide-content">
<img ng-src="{{splashImage}}" />
<button ng-click="hide()">Continue</button>
</div>
</div>CSS (e.g. guide.css)
.guide-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
background: rgba(0, 0, 0, 0.85);
display: flex;
align-items: center;
justify-content: center;
}Key Points
angular.module('beamng.apps').run(...)- the.run()block executes when the module is bootstrapped, before any routing or view rendering- Append to
document.body- puts your container at the top level of the DOM, outside any Angular view hierarchy $compile(container)($rootScope.$new())- creates a new child scope and compiles the element so Angular processesng-controller,ng-include, etc.- Use
ng-iffor visibility - don't just toggle CSS;ng-ifremoves/adds the DOM entirely, preventing event interference when hidden z-index: 99999- ensures your overlay is above all other UI elements
CEF Asset Path Rule
⚠️ All UI assets (images, CSS, HTML) must be under the /ui/ directory tree. BeamNG's CEF (Chromium Embedded Framework) cannot access files outside /ui/.
✅ /ui/modModules/guide/screenshot.jpg - works
❌ /guides/quickStart/screenshot.jpg - broken image, no errorPlace mod UI assets at paths like /ui/modModules/yourmod/ to ensure CEF can load them.
Phone UI System
Phone overlay system - toggleable in-game phone with apps, minimap, time display, and state management.
server/commands - Camera & Input Commands
Reference for `server/commands.lua`. Provides camera management functions - switching between free/game cameras, positioning, and deprecated global camera accessors.