RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Reference

UI

BeamNG ImGui API ReferenceBeamNG ImGui Cheat SheetBeamNG ImGui Data TypesBeamNG World Editor ImGui WindowsBeamNG ImGui Flags & ConstantsBeamNG ImGui Patterns & ExamplesBeamNG ImGui Style Guide

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

ImGui

BeamNG World Editor ImGui Windows

Editor extensions live in `lua/ge/extensions/editor/` and use the `editor` API alongside ImGui.

Creating an Editor Tool Window

Editor extensions live in lua/ge/extensions/editor/ and use the editor API alongside ImGui.

Minimal Editor Extension

local M = {}
local logTag = 'editor_myTool'
local im = ui_imgui
local toolWindowName = "editor_myTool_window"

local function onEditorGui()
  if not editor.isWindowVisible(toolWindowName) then return end
  
  if editor.beginWindow(toolWindowName, "My Tool") then
    im.Text("Tool content here")
    
    if im.Button("Do Something") then
      log('I', logTag, "Button clicked")
    end
  end
  editor.endWindow()
end

local function onWindowMenuItem()
  editor.showWindow(toolWindowName)
end

local function onEditorInitialized()
  editor.registerWindow(toolWindowName, im.ImVec2(400, 300))
  editor.addWindowMenuItem("My Tool", onWindowMenuItem)
  log('I', logTag, "My Tool initialized")
end

local function onActivate()
  log('I', logTag, "My Tool activated")
end

M.onEditorGui = onEditorGui
M.onEditorInitialized = onEditorInitialized
M.onWindowMenuItem = onWindowMenuItem
M.onActivate = onActivate
return M

Key Differences from Regular ImGui

FeatureRegular ExtensionEditor Extension
Render hookonUpdate()onEditorGui()
Window beginim.Begin("Name")editor.beginWindow(name, title)
Window endim.End()editor.endWindow()
RegistrationN/Aeditor.registerWindow()
Menu entryN/Aeditor.addWindowMenuItem()
VisibilityManual flageditor.isWindowVisible()
Show/HideManualeditor.showWindow() / editor.hideWindow()

Editor Window with Menu Bar

local function onEditorGui()
  if not editor.isWindowVisible(toolWindowName) then return end
  
  if editor.beginWindow(toolWindowName, "My Tool", im.WindowFlags_MenuBar) then
    if im.BeginMenuBar() then
      if im.BeginMenu("File") then
        if im.MenuItem1("Load") then loadData() end
        if im.MenuItem1("Save") then saveData() end
        im.EndMenu()
      end
      im.EndMenuBar()
    end
    
    -- Window content
    im.Text("Content")
  end
  editor.endWindow()
end

Editor Helper: Object Selection

-- Select a scene object
editor.selectObjectById(objectId)

-- Get current selection
local selection = editor.selection
if selection and selection.object and #selection.object > 0 then
  local selectedObj = scenetree.findObjectById(selection.object[1])
end

-- Show notification
editor.showNotification("Operation complete!")

Editor Helper: Icon Buttons

-- Editor provides icon buttons (only available in editor context)
if editor.uiIconImageButton then
  editor.uiIconImageButton(editor.icons.save, im.ImVec2(24, 24))
  editor.uiIconImageButton(editor.icons.delete, im.ImVec2(24, 24))
end

Periodic Updates in Editor

local lastUpdateTime = 0
local UPDATE_INTERVAL = 5  -- seconds

function M.onEditorUpdate()
  -- Called every frame when editor is active
  if os.time() - lastUpdateTime > UPDATE_INTERVAL then
    lastUpdateTime = os.time()
    -- Do periodic work (refresh lists, validate data, etc.)
  end
end

Editor Preferences

-- Read editor preferences
if editor and editor.getPreference then
  local dpiAware = editor.getPreference("ui.general.dpiAware")
  local lineThickness = editor.getPreference("gizmos.general.lineThicknessScale")
end

Debug Drawing in Editor

-- Draw debug shapes in the 3D viewport
function M.onEditorUpdate()
  if pendingPlacement then
    local hit = cameraMouseRayCast(true)
    if hit then
      local pos = vec3(worldEditorCppApi.snapPositionToGrid(hit.pos))
      local lineWidth = editor.getPreference("gizmos.general.lineThicknessScale") * 4
      
      -- Draw crosshair at cursor position
      debugDrawer:drawLineInstance(pos - vec3(2,0,0), pos + vec3(2,0,0), lineWidth, ColorF(1,0,0,1))
      debugDrawer:drawLineInstance(pos - vec3(0,2,0), pos + vec3(0,2,0), lineWidth, ColorF(0,1,0,1))
      debugDrawer:drawLineInstance(pos - vec3(0,0,2), pos + vec3(0,0,2), lineWidth, ColorF(0,0,1,1))
    end
  end
end

Creating Objects from Editor

-- Create a BeamNGTrigger
local obj = worldEditorCppApi.createObject("BeamNGTrigger")
if obj then
  obj:setName("myTriggerName")
  obj:registerObject("")
  obj:setPosition(hitPosition)
  
  -- Add to appropriate parent group
  local parent = scenetree.MissionGroup
  parent:addObject(obj)
  
  -- Select it
  editor.selectObjectById(obj:getID())
end

BeamNG ImGui Data Types

ImGui uses C-style pointers for mutable values. BeamNG wraps these as Lua tables with a `[0]` index.

BeamNG ImGui Flags & Constants

All flags are accessed as `im.FlagName` where `im = ui_imgui`. Combine with `+` operator.

On this page

Creating an Editor Tool WindowMinimal Editor ExtensionKey Differences from Regular ImGuiEditor Window with Menu BarEditor Helper: Object SelectionEditor Helper: Icon ButtonsPeriodic Updates in EditorEditor PreferencesDebug Drawing in EditorCreating Objects from Editor