A coherent UI system for Garry's Mod.

BUI is a reusable VGUI component library and design system. It centralizes visual tokens, scaling, fonts, layouts, frame presets, animation, overlays and server-owned configuration so separate addons can share one visual language.

Dependency direction: application addon → BUI. BUI contains no DarkRP references and remains usable under Sandbox or another gamemode.

Theme-driven

Components resolve colours and geometry while painting, so open interfaces reflect theme changes.

Responsive

Geometric scale, axis helpers and clamped window sizes handle 720p through 4K and ultrawide.

Event-driven

Fonts, scale, config and animations update through hooks instead of permanent panel polling.

Installation

Place benjis_ui in garrysmod/addons/. The autorun loader sends client files with AddCSLuaFile, loads shared modules in both realms, and loads realm-specific modules only where valid. Restart the server after first installation.

garrysmod/
└── addons/
    ├── benjis_ui/
    │   ├── lua/autorun/bui_init.lua
    │   ├── lua/bui/...
    │   └── documentation/index.html
    └── your_addon/
        └── lua/autorun/your_addon.lua

Dependents should wait for BUILoaded if their autorun file can execute before BUI. The global BUI.Version is the fast path when BUI is already initialized.

local function initialize()
    if not BUI or not BUI.Version then return end
    hook.Remove("BUILoaded", "Example.Load")
    -- Register the addon's components and screens here.
end

initialize()
hook.Add("BUILoaded", "Example.Load", initialize)

Addon structure and realms

DirectoryRealmResponsibility
core/shared/clientNamespace, validation, scaling, fonts, cached materials, drawing and animation.
themes/sharedTheme registration and semantic colour lookup.
components/clientReusable VGUI controls and overlays.
layouts/clientStack, grid, padding, centering and spacer helpers.
presets/clientReusable internal frame composition.
positions/clientReusable screen placement and opening/closing presentations.
config/server/clientPersistence, validation, synchronization and the superadmin screen.
demo/clientLive component gallery.

Create panels only on the client. Theme definitions, configuration schemas and settings category registration are shared. The server is authoritative for persisted configuration.

Your first menu

local frame = BUI.CreateFrame({
    title = "Inventory",
    width = 980,
    height = 680,
    preset = "sidebar"
})

BUI.SetPadding(frame.Sidebar, 12)

local navigation = BUI.Create("BUI.VerticalTabs", frame.Sidebar, {
    vertical = true,
    tabs = {
        {id = "items", label = "Items", icon = "cart"},
        {id = "settings", label = "Settings", icon = "settings"}
    }
})
navigation:Dock(FILL)

local card = BUI.Create("BUI.Card", frame.Main, {title = "Available items"})
card:Dock(FILL)

BUI.Create creates a registered component and passes its options to Configure. Specialized application panels may still use ordinary VGUI; use BUI for shared primitives and tokens.

Themes and colours

The bundled dark theme is default; light is also complete. A theme is one object containing semantic colours. Components never need a separate light implementation.

background
surface / surfaceAlt
elevated
border
text / textMuted
accent states
positive
warning
destructive
overlay / shadow
BUI.RegisterTheme("ocean", {
    name = "Ocean",
    colors = {
        background = Color(7, 14, 20),
        surface = Color(13, 27, 37),
        surfaceAlt = Color(18, 36, 48),
        elevated = Color(23, 43, 56),
        border = Color(43, 68, 82),
        text = Color(238, 247, 250),
        textMuted = Color(146, 171, 181),
        textDisabled = Color(91, 112, 121),
        accent = Color(38, 178, 211),
        accentHover = Color(58, 195, 225),
        accentActive = Color(27, 148, 180),
        positive = Color(60, 190, 126),
        warning = Color(238, 176, 63),
        destructive = Color(230, 77, 87),
        overlay = Color(0, 0, 0, 180),
        shadow = Color(0, 0, 0, 140)
    }
})

BUI.SetTheme("ocean")
local accent = BUI.GetColor("accent")

When SetTheme is used, configurable base overrides are updated from the chosen theme and BUIThemeChanged is emitted.

Semantic fonts

Use roles, not font names. BUI ships Display, Title, Heading, Subheading, Body, BodyBold, Small, Caption, Button, HUD, HUDSmall and Numeric. Fonts regenerate after screen size, scale or typography configuration changes.

draw.SimpleText(
    "Quartermaster",
    BUI.GetFont("Heading"),
    x, y,
    BUI.GetColor("text")
)

BUI.RegisterFontRole("Price", {
    size = 20,
    weight = 700
})

The configured family defaults to Roboto. Garry's Mod/OS font fallback applies if an administrator enters an unavailable family.

Responsive scaling

FunctionUse
BUI.Scale(n)General controls, icons, spacing and text-adjacent geometry.
BUI.ScaleW(n)Width-sensitive application geometry.
BUI.ScaleH(n)Height-sensitive application geometry.
BUI.ClampScale(n,min,max)Scale with hard usability bounds.
BUI.ScreenCategory()compact, standard, large or ultrawide.
BUI.ResponsiveSize(...)Clamped frame size respecting screen margins.
local iconSize = BUI.Scale(18)
local sidebarWidth = BUI.ScaleW(224)

if BUI.ScreenCategory() == "compact" then
    detailsPanel:SetVisible(false)
end

local width, height = BUI.ResponsiveSize(1100, 720, 1500, 960)

The scale uses a 1920×1080 reference with clamped geometric scaling and an admin-controlled multiplier. This avoids both blind 4K enlargement and tiny 720p controls.

Icons

HUD and navigation icons use BUI's bundled, server-downloaded icon set. Remaining utility icons fall back to Garry's Mod materials. Registered materials are cached and can still be extended by dependent addons.

BUI.RegisterIcon("inventory", "icon16/box.png")

local material = BUI.GetIcon("inventory")
BUI.DrawIcon("inventory", x, y, BUI.Scale(16), BUI.GetColor("text"))

local button = BUI.Create("BUI.Button", parent, {
    text = "Inventory",
    icon = "inventory"
})

Bundled IDs include close, check, info, warning, error, search, settings, user, users, home, money, heart, shield, briefcase, refresh, external, menu, star, lock, unlock, food, cart, gun, car, laws, terminal, arrow and chevron.

Animations

A single temporary Think hook services active animations and removes itself when the queue empties. Disabling animations applies target values immediately.

BUI.Animate(panel, "width", panel:GetWide(), BUI.Scale(320), 0.18,
    function(value)
        if IsValid(panel) then panel:SetWide(value) end
    end
)

BUI.FadeIn(panel, 0.16)
BUI.FadeOut(panel, 0.14, true)

Available easing names are linear, out and inout. Duration is adjusted by the configured animation speed.

Component catalogue

Every component is created with BUI.Create(class, parent, options). Most options return the configured panel, accept normal VGUI docking afterward, and expose standard VGUI events in addition to the callbacks listed here.

ClassPurpose and important optionsCommon methods/events
BUI.PanelThemed surface. surface transparent border paddingNormal DPanel API.
BUI.CardElevated content group. titleTitle, normal child parenting.
BUI.Frame, BUI.WindowResponsive application window. title width height presetGetContent, CloseAnimated, Enter submit, Escape close.
BUI.ScrollPanelThemed vertical scroll container.GetCanvas, Clear, standard DScrollPanel.
BUI.ButtonPrimary action. text icon variant disabledonClick(panel), SetEnabled.
BUI.IconButton, BUI.TextButtonButton variants sharing the button API.Same as BUI.Button.
BUI.Label, BUI.RichLabelSemantic text. text role muted wrapSetText, SetWrap.
BUI.TextEntry, BUI.NumberEntryText/numeric input. placeholder value numeric multilineonChange(value,panel), onSubmit(value,panel).
BUI.FieldAccessible form row pairing a permanent label and optional description with an input control. label description component controlGetControl(); normally use BUI.CreateField.
BUI.SearchBoxClient-side search input with icon.onChange, onSubmit.
BUI.Checkbox, BUI.ToggleBoolean input with label. value textSetValue, GetValue, onChange.
BUI.SliderLightweight numeric range. min max value decimalsSetValue, GetValue, onChange.
BUI.ComboBoxDropdown of {label,value,selected} objects or strings.AddChoice, onChange(value,panel,index).
BUI.Tabs, BUI.HorizontalTabs, BUI.VerticalTabsSelectable navigation. tabs vertical activeAddTab, Select, onChange(id,tabs).
BUI.Sidebar, BUI.NavbarSemantic navigation aliases using the tabs API.Same as tabs.
BUI.List, BUI.ListItemStacked interactive items. List options: items spacing.AddItem, SetItems, ClearItems, item SetSelected.
BUI.PlayerRowAvatar, name and job for a player. playeronClick(player,row).
BUI.TableColumn/row data display. Columns accept key, label, width, render.SetRows, onRowClick(row,index,table).
BUI.AvatarPlayer avatar wrapper. player sizeNormal panel sizing.
BUI.DividerSemantic one-pixel separator.Dock and size normally.
BUI.Badge, BUI.TooltipCompact state label. text kindKinds: neutral, info, success, warning, error.
BUI.ProgressBarAnimated 0–1 progress. value colorSetValue(value,animate).
BUI.LoadingLightweight loading indicator. textRemove when work completes.
BUI.EmptyStateEmpty/error content placeholder. icon title messageNormal panel API.
BUI.IconTextRowIcon plus text metadata row.Configure.
BUI.Header, BUI.FooterSemantic surface containers.Panel API.
BUI.Modal, BUI.ConfirmationModalFocus-trapping overlay with action objects.CloseAnimated; use OpenModal/Confirm.
BUI.ToastTimed stacked notification with optional action.Dismiss; normally use BUI.Notify.
BUI.ContextMenuContext menu base; normally use BUI.OpenContextMenu.Standard DMenu.

Inputs example

local form = BUI.CreateStack(parent, {direction = "vertical", gap = 10})

local nameField, nameEntry = BUI.CreateField(form, {
    label = "Character name",
    description = "This name is visible to other roleplay players.",
    component = "BUI.TextEntry",
    control = {
        placeholder = "Example: Morgan Price",
        onSubmit = function(value)
            submitCharacter(value)
        end
    }
})
form:Add(nameField)

form:Add(BUI.Create("BUI.Toggle", form, {
    text = "Receive announcements",
    value = true,
    onChange = function(enabled)
        preferences.announcements = enabled
    end
}))

List and table examples

local list = BUI.Create("BUI.List", parent, {
    items = {
        {text = "Overview", icon = "home"},
        {text = "Members", icon = "users"}
    }
})

local dataTable = BUI.Create("BUI.Table", parent, {
    columns = {
        {key = "name", label = "Name"},
        {key = "status", label = "Status"}
    },
    rows = {
        {name = "Generator", status = "Online"},
        {name = "Relay", status = "Offline"}
    },
    onRowClick = function(row)
        print(row.name)
    end
})

Frames and presets

Preset IDGenerated regionsNotes
centeredContentStandard centered padded window.
sidebarSidebar, MainLeft navigation and application content.
right_sidebarSidebar, MainRight-aligned navigation/inspector.
top_navigationNavbar, MainHorizontal application navigation.
dashboardSidebar, Main, FooterSidebar can be disabled with sidebar=false.
fullscreenContentScreen-sized, fixed application.
modalContentSmall non-draggable focused frame.
splitLeft, RightWeighted proportional panes.
local frame = BUI.CreateFrame({
    title = "Inspector",
    width = 1000,
    height = 650,
    preset = "split",
    leftWeight = 2,
    rightWeight = 1,
    closeOnEscape = true,
    position = "sidebar",
    side = "left",
    fullHeight = true,
    onSubmit = function(activeFrame)
        save(activeFrame)
    end
})

Frame positions

A preset builds regions inside a frame; a position controls where the finished frame lives and how it enters or exits. They are intentionally composable. Built-in positions are center, sidebar, sidebar_left, sidebar_right, top_left, top_right, bottom_left, bottom_right and fullscreen. The generic sidebar position accepts side="left"|"right", fullHeight, edgeMargin and positionDuration.

local drawer = BUI.CreateFrame({
    title = "Inventory",
    width = 920,
    preset = "dashboard",
    position = "sidebar",
    side = "right",
    fullHeight = true
})

Layout system

Stacks and weighted columns

local row = BUI.CreateStack(parent, {
    direction = "horizontal",
    gap = 12,
    padding = 8
})
row:Dock(FILL)
row:Add(leftPanel, 2)
row:Add(centerPanel, 3)
row:Add(rightPanel, 1)

Responsive grid and wrapping

local grid = BUI.CreateGrid(scrollPanel, {
    minColumnWidth = 260,
    rowHeight = 150,
    gap = 12
})
grid:Dock(TOP)

for _, record in ipairs(records) do
    grid:Add(buildCard(record))
end

BUI.Grid, BUI.ResponsiveGrid and BUI.Wrap share this responsive grid behavior. Use BUI.SetPadding(panel,...), BUI.Spacer(parent,size,horizontal) and BUI.Center(panel,w,h) for small composition tasks. Layout occurs during VGUI invalidation, not a Think loop.

Notifications, confirmations and context

BUI.Notify({
    type = "success",
    title = "Purchase complete",
    message = "The shipment was added to your inventory.",
    duration = 5,
    action = "Open",
    callback = function(toast)
        openInventory()
    end
})

BUI.Confirm({
    title = "Delete this preset?",
    message = "This action cannot be undone.",
    destructive = true,
    confirmText = "Delete",
    onConfirm = deletePreset
})
BUI.AttachTooltip(button, "Refresh available jobs")

BUI.OpenContextMenu({
    {label = "Copy identifier", callback = copyIdentifier},
    {divider = true},
    {label = "Open profile", callback = openProfile}
})

Toasts support info, success, warning and error, stack in the configured screen corner, and remove themselves. Modals take an actions array of {label,variant,callback,close}.

Interactive world surfaces

BUI.CreateWorldSurface creates a theme-aware 3D2D interaction surface attached to an entity. It performs ray-plane cursor projection, range and eye-trace checks, button hit testing, hover state, cleanup and E-key dispatch without creating a Think hook per entity.

local screen = BUI.CreateWorldSurface(self, {
    width = 600,
    height = 600,
    scale = 0.04,
    maxDistance = 180,
    getTransform = function(entity)
        return entity:LocalToWorld(Vector(20, 0, 55)),
            entity:LocalToWorldAngles(Angle(0, 90, 90))
    end
})

screen:SetButtons({
    {
        x = 30, y = 480, w = 540, h = 70,
        label = "COLLECT",
        icon = "money",
        enabled = function(entity) return entity:GetStoredMoney() > 0 end,
        onClick = function(entity)
            net.Start("MyAddon.Collect")
            net.WriteEntity(entity)
            net.SendToServer()
        end
    }
})

function ENT:Draw()
    self:DrawModel()
    screen:Paint(function(surfaceObject, width, height, x, y, hovered)
        draw.RoundedBox(8, 0, 0, width, height, BUI.GetColor("background"))
        for _, worldButton in ipairs(surfaceObject.Buttons) do
            surfaceObject:DrawButton(worldButton, hovered == worldButton)
        end
    end)
end

World-surface callbacks are clientside convenience only. Every requested action must still be range-checked, permission-checked and value-validated on the server. Call surfaceObject:Remove() from the client entity's OnRemove.

Configuration

Run bui_config as a superadmin. Appearance, typography, global UI, HUD and registered addon categories are edited in a framework-built screen. Changes persist in garrysmod/data/benjis_ui/config.json.

  • Appearance: theme, base colours, radius, border style/width, shadow and opacity.
  • Typography: family, base size, heading scale and HUD scale.
  • UI: global scale, animations/speed, toast position, blur, sidebar and frame dimensions.
  • HUD: scale, anchor, opacity and spacing.
  • Reset section and restore-all actions require confirmation.
local accent = BUI.GetConfig("appearance", "accent")
local animations = BUI.GetConfig("ui", "animations", true)

BUI.RegisterSettingsCategory("inventory", {
    label = "Inventory",
    icon = "cart",
    defaults = {compact = false},
    Validate = function(input, fallback)
        input = istable(input) and input or {}
        return {compact = isbool(input.compact) and input.compact or fallback.compact}
    end,
    Render = function(panel, draft, addRow)
        draft.inventory = draft.inventory or {compact = false}
        local toggle = BUI.Create("BUI.Toggle", panel, {
            value = draft.inventory.compact,
            onChange = function(value) draft.inventory.compact = value end
        })
        addRow(panel, "Compact item cards", toggle)
    end
})

Settings categories must provide safe defaults and a validator. Render is client-only; guard it when the registration file is shared.

Networking and security

The server loads and validates the complete configuration. Clients request a snapshot once after InitPostEntity. Updates are compressed, size-bounded and accepted only from valid superadmins, with a per-player rate limit. Clients cannot directly select arbitrary persistence paths or bypass schema limits.

MessageDirectionPurpose
BUI.ConfigRequestClient → serverRequest authoritative state.
BUI.ConfigSyncServer → clientCompressed validated configuration snapshot.
BUI.ConfigUpdateSuperadmin client → serverSave, reset section, or restore defaults.

Do not use these internal messages as an addon state transport. Register an extension category for shared BUI configuration and use a separate validated net channel for unrelated application data.

Hooks

HookArgumentsWhen
BUILoadedversionAll framework modules are available.
BUIThemeChangedid, previousIdBUI.SetTheme changes theme.
BUIConfigChangedconfig, sourceValidated config applied locally/server-side.
BUIScaleChangedscale, oldW, oldH, newW, newHResolution/config scale changes.
BUIFontsChangedfontNamesSemantic fonts regenerate.
BUIThemeRegisteredid, themeA theme is added.
BUIPresetRegisteredid, definitionA frame preset is added.
BUIPositionRegisteredid, definitionA frame position is added.
BUIFramePositionedframe, id, optionsA position is applied to a frame.
BUISettingsCategoryRegisteredid, definitionAn addon settings category is added.
hook.Add("BUIConfigChanged", "Inventory.RefreshStyle", function(config, source)
    if IsValid(Inventory.Frame) then
        Inventory.Frame:InvalidateLayout(true)
    end
end)

Custom themes, presets, positions and components

Preset

BUI.RegisterPreset("inspector", {
    name = "Inspector",
    Apply = function(frame, options)
        frame.Main = vgui.Create("DPanel", frame:GetContent())
        frame.Main:SetPaintBackground(false)
        frame.Main:Dock(FILL)

        frame.Inspector = BUI.Create("BUI.Panel", frame:GetContent(), {})
        frame.Inspector:Dock(RIGHT)
        frame.Inspector:SetWide(BUI.Scale(options.inspectorWidth or 280))
    end
})

Position

BUI.RegisterPosition("lower_center", {
    Open = function(frame, options, animated)
        local x = (ScrW() - frame:GetWide()) * .5
        local y = ScrH() - frame:GetTall() - BUI.Scale(20)
        frame:SetPos(x, y)
        if animated then BUI.FadeIn(frame, .14) end
    end,
    Close = function(frame)
        BUI.FadeOut(frame, .12, true)
    end
})

Component

local PANEL = {}

function PANEL:Init()
    self.Value = 0
    self:SetTall(BUI.Scale(48))
end

function PANEL:Configure(options)
    self.Value = tonumber(options.value) or 0
    return self
end

function PANEL:Paint(w, h)
    BUI.DrawPanel(0, 0, w, h, BUI.GetColor("surface"))
    draw.SimpleText(self.Value, BUI.GetFont("Numeric"),
        BUI.Scale(12), h * .5, BUI.GetColor("text"),
        TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end

BUI.RegisterComponent("Inventory.Counter", PANEL, "DPanel")

Application components should use their own namespace. Register only controls that are genuinely reused; a page-specific composition can stay a local builder function.

Creating an Addon with BUI

This minimal addon adds a themed player directory without modifying BUI.

my_directory/
└── lua/
    ├── autorun/my_directory.lua
    └── my_directory/cl_menu.lua
-- lua/autorun/my_directory.lua
if SERVER then AddCSLuaFile("my_directory/cl_menu.lua") end

local function load()
    if not BUI or not BUI.Version then return end
    if CLIENT then include("my_directory/cl_menu.lua") end
end

load()
hook.Add("BUILoaded", "MyDirectory.Load", load)
-- lua/my_directory/cl_menu.lua
local function openDirectory()
    local frame = BUI.CreateFrame({
        title = "Player Directory",
        width = 900,
        height = 650,
        preset = "centered"
    })

    local search = BUI.Create("BUI.SearchBox", frame:GetContent(), {
        placeholder = "Search players"
    })
    search:Dock(TOP)
    search:DockMargin(BUI.Scale(16), BUI.Scale(12), BUI.Scale(16), BUI.Scale(10))

    local list = BUI.Create("BUI.ScrollPanel", frame:GetContent(), {dock = FILL})
    list:DockMargin(BUI.Scale(16), 0, BUI.Scale(16), BUI.Scale(16))

    local function rebuild(query)
        list:Clear()
        query = string.lower(query or "")
        for _, ply in ipairs(player.GetAll()) do
            if query == "" or string.find(string.lower(ply:Nick()), query, 1, true) then
                local row = BUI.Create("BUI.PlayerRow", list, {
                    player = ply,
                    onClick = function(selected)
                        SetClipboardText(selected:SteamID())
                        BUI.Notify("Copied", selected:SteamID(), "success")
                    end
                })
                row:Dock(TOP)
            end
        end
    end

    search.OnValueChanged = rebuild
    rebuild("")
end

concommand.Add("player_directory", openDirectory)

Add a settings category only if the option is server-wide. Keep personal, ephemeral UI state client-local.

DarkRP integration example

The separate benjis_darkrp_ui addon demonstrates dependency use. It registers its settings through BUI.RegisterSettingsCategory, creates domain-specific player/item rows with BUI.RegisterComponent, uses dashboard/sidebar presets, and reads all visual tokens from BUI.

BDUI.RegisterF4Section("crafting", {
    label = "Crafting",
    icon = "settings",
    order = 75,
    Available = function()
        return istable(Crafting.Recipes) and not table.IsEmpty(Crafting.Recipes)
    end,
    Build = function(parent, frame)
        local grid = BUI.CreateGrid(parent, {minColumnWidth = 280})
        grid:Dock(TOP)
        -- Populate recipe cards here.
    end
})

This public DarkRP extension API belongs to the integration addon, not BUI. It lets another DarkRP addon add an F4 section without editing either core.

Performance recommendations

  • Resolve theme values in Paint, but cache materials and expensive domain data outside it.
  • Use docking, stack and grid invalidation instead of manual positioning in Think.
  • Use BUI.Animate; its hook exists only while animation work is active.
  • Create fonts only through roles and call RefreshFonts
  • For long server lists, rebuild on search/sort/player events, not every frame.
  • Throttle eye traces for contextual HUDs and cache the current result briefly.
  • Remove panel-owned timers/hooks in OnRemove when adding any yourself.
  • Do not network search text, selected tabs, hover state or other client-only state.
  • Use blur sparingly; BUI applies it only when enabled and requested by a frame.

Common mistakes

MistakeCorrect approach
Using placeholder text as the only explanation for an input.Use BUI.CreateField with a permanent label and description. A placeholder is only an example or format hint.
Hardcoding Color(20,20,20) in every panel.Use BUI.GetColor("surface") or add a semantic theme token.
Multiplying every coordinate by ScrW()/1920.Use general/axis scaling and responsive max sizes.
Creating surface.CreateFont in Paint.Register a semantic role once.
Including client component files on the server.Use AddCSLuaFile; include them only under CLIENT.
Assuming BUI autoruns first.Use BUI.Version plus the BUILoaded hook.
Sending config directly to clients from an unvalidated receiver.Use a settings category and BUI's server-owned configuration.
Recreating the root frame for each tab.Keep the root/navigation and replace only content.
Registering a huge generic abstraction for one screen.Keep domain composition local; register only reusable components.

Public API reference

Functions below are supported public APIs. Module-local functions and the three configuration net messages are internal implementation.

FunctionArguments → returnDescription
BUI.Create(string class, Panel? parent, table? options) → Panel?Create and configure a registered component.
BUI.CreateField(Panel parent, table options) → BUI.Field, PanelCreate a labelled form field and return both its container and configured control. Use permanent labels for meaning; placeholders are examples or format hints.
BUI.CreateFrame(table options) → BUI.FrameCreate a responsive window; supports title, dimensions, internal preset, screen position, popup, sizing and submit options.
BUI.CreateWorldSurface(Entity entity, table options) → WorldSurface?Create an entity-bound interactive 3D2D surface with width, height, scale, maximum distance and transform options.
WorldSurface:SetButtons(table buttons) → WorldSurfaceSet hit-tested buttons supporting geometry, label, icon, visible, enabled and onClick fields.
WorldSurface:Paint(function callback)Paint at the configured world transform and pass dimensions, projected cursor and hovered button.
WorldSurface:DrawButton(table button, boolean hovered)Draw a world button using current BUI theme tokens and world font roles.
BUI.RegisterComponent(string name, table panel, string? base) → stringRegister a VGUI component and record it in BUI.Components.
BUI.RegisterTheme(string id, table theme) → booleanRegister a semantic theme object.
BUI.GetTheme(string? id) → tableReturn requested/current theme, falling back to dark.
BUI.SetTheme(string id) → booleanSet a registered theme locally and emit hooks.
BUI.GetColor(string token, number? alpha) → ColorResolve theme/config colour.
BUI.RegisterFontRole(string role, table definition) → booleanAdd/update a semantic font role.
BUI.RefreshFonts()Regenerate semantic fonts from current scaling/configuration.
BUI.GetFont(string role) → stringReturn the generated surface font name.
BUI.Scale(number value) → numberGeneral clamped UI scaling.
BUI.ScaleW, ScaleH(number value) → numberAxis-aware scaling.
BUI.ClampScale(number value, number? min, number? max) → numberScale with explicit output bounds.
BUI.GetScale() → numberCurrent effective UI multiplier.
BUI.ScreenCategory() → stringReturn compact, standard, large or ultrawide.
BUI.ResponsiveSize(w,h,maxW?,maxH?) → w,hGet clamped menu dimensions.
BUI.RegisterIcon(string id, string materialPath) → booleanCache a named material.
BUI.GetIcon(string idOrPath) → IMaterialResolve cached icon.
BUI.FitText(string text, string role, number maxWidth, table? fallbackRoles) → string, string, number, stringChoose a smaller semantic font when needed, then safely ellipsize text to the available width.
BUI.WrapText(string text, string role, number maxWidth, number maxLines, table? fallbackRoles) → table, string, stringWrap text within a width and line budget, using semantic fallback fonts before truncating.
BUI.DrawIcon(id,x,y,size,color?)Draw a named icon.
BUI.DrawPanel(x,y,w,h,color?,radius?,borderColor?,borderWidth?)Draw themed surface, border and shadow.
BUI.DrawBlur(Panel panel, number? strength)Draw optional configured background blur.
BUI.TextSize(any text, string? role) → w,hMeasure semantic text.
BUI.Animate(panel,key,from,target,duration,update,complete?,easing?)Schedule lightweight numeric animation.
BUI.FadeIn, FadeOut(panel,duration?,remove?)Convenience alpha transitions.
BUI.Notify(table options) → BUI.ToastShow stacked notification. Also accepts (title,message,type).
BUI.OpenModal(table options) → BUI.ModalOpen arbitrary action modal.
BUI.Confirm(table options) → BUI.ModalOpen cancel/confirm modal.
BUI.AttachTooltip(Panel panel, string text)Attach lightweight themed tooltip behavior.
BUI.OpenContextMenu(table items) → DMenuOpen action/divider menu at cursor.
BUI.RegisterPreset(string id, table definition) → booleanRegister frame composition with Apply.
BUI.ApplyPreset(Panel frame, string id, table? options) → booleanApply registered preset.
BUI.RegisterPosition(string id, table definition) → booleanRegister a screen presentation with Open and optional Close.
BUI.GetPosition(string id) → table?Return a registered frame-position definition.
BUI.ApplyPosition(Panel frame, string id, table? options, boolean? animated) → booleanPlace or animate a frame using a registered position.
BUI.ClosePosition(Panel frame) → booleanRun the active position's close presentation when available.
BUI.CreateStack(parent, options?) → BUI.StackCreate horizontal/vertical/equal/weighted stack.
BUI.CreateGrid(parent, options?) → BUI.GridCreate fixed/responsive grid.
BUI.Spacer(parent,size?,horizontal?) → PanelCreate non-painting spacer.
BUI.SetPadding(panel,top,right?,bottom?,left?) → PanelScale and apply dock padding.
BUI.Center(panel,width,height) → PanelScale, size and center a panel.
BUI.RegisterSettingsCategory(string id, table definition) → booleanExtend server configuration and admin UI.
BUI.GetConfig(section,key?,fallback?) → anyRead current validated config.
BUI.ValidateConfig(table input) → tableReturn safe bounded config.
BUI.ApplyConfig(table config, any? source)Validate/apply and emit refresh hooks.
BUI.ResetConfigSection(string section) → booleanReset section locally; admin UI is required for authoritative server reset.
BUI.OpenConfig() → BUI.Frame?Open superadmin-only settings.
BUI.OpenDemo() → BUI.FrameOpen component gallery.
BUI.Util.Clone(any value) → anyDeep-copy ordinary tables and colours.
BUI.Util.Merge(table target, table source) → tableDeep merge configuration-style tables.
BUI.Util.ClampNumber(value,min,max,fallback) → numberCoerce and clamp numeric input.
BUI.Util.SafeColor(value,fallback) → ColorValidate RGBA tables.
BUI.Emit(string event, ...) → anyRun hook.Run("BUI" .. event,...).

Console commands

CommandAccessPurpose
bui_demoClientOpen live component gallery.
bui_configSuperadminOpen authoritative configuration.