MAEngine

WebUI

Full HTML/CSS/JS UI system powered by Ultralight browser engine

WebUI

Availability: Client Only

WebUI provides a full HTML/CSS/JS UI system powered by the Ultralight browser engine. Use standard web technologies to create complex, interactive interfaces.


Quick Start

-- Client/ui.lua
local hud = nil

Client.Subscribe("Ready", function()
    hud = WebUI.CreateAtScale("HUD", "hud/index.html")
    hud:SetFullscreen(true)
    WebUI.ShowViewport(false)

    -- Receive events from JavaScript
    hud:Subscribe("ButtonClicked", function(button_id)
        Events.CallServer("UIButtonClicked", { button = button_id })
    end)
end)

-- Bridge Store values to JavaScript
Store.Subscribe("player.health", function(value)
    if hud then hud:CallEvent("UpdateHealth", value) end
end)

Viewport Control

WebUI.ShowViewport

Show the WebUI overlay.

WebUI.ShowViewport()           -- Show without input capture
WebUI.ShowViewport(false)      -- Show without input capture (HUD mode)
WebUI.ShowViewport(true)       -- Show with input capture (menu mode)

WebUI.HideViewport

Hide the WebUI overlay.

WebUI.HideViewport()

WebUI.SetFocusMode

Control how input is routed between UI and game.

WebUI.SetFocusMode("none")   -- Game only, cursor hidden
WebUI.SetFocusMode("soft")   -- Mouse to UI, keyboard to game
WebUI.SetFocusMode("hard")   -- All input to UI, cursor visible
ModeMouseKeyboardCursorUse Case
noneGameGameHiddenHUD overlay only
softUIGameShownInteractive HUD
hardUIUIShownMenus, forms

Constructors

WebUI(name, url, visible)

Create a fullscreen WebUI.

local ui = WebUI("HUD", "hud/index.html", true)
local ui = WebUI("Menu", "menu/index.html", false)

Parameters:

  • name (string) - Unique identifier for this WebUI
  • url (string) - Path to HTML file relative to games/<game>/Client/UI/
  • visible (boolean, optional) - Initial visibility, default true

WebUI.CreateWithSize

Create a WebUI with specific dimensions.

local ui = WebUI.CreateWithSize("Minimap", "minimap/index.html", 300, 300)

Parameters:

  • name (string) - Unique identifier
  • url (string) - Path to HTML file
  • width (integer) - Width in pixels
  • height (integer) - Height in pixels

WebUI.CreateAtScale

Create a WebUI scaled relative to viewport.

local ui = WebUI.CreateAtScale("HUD", "hud/index.html", 0.5)  -- 50% of viewport
local ui = WebUI.CreateAtScale("HUD", "hud/index.html")       -- 100% default

Parameters:

  • name (string) - Unique identifier
  • url (string) - Path to HTML file
  • scale (number, optional) - Scale factor (0.0 to 1.0), default 1.0

Instance Methods

Visibility & Focus

ui:SetVisible(true)        -- Show/hide
ui:IsVisible()             -- Check visibility (boolean)
ui:SetFocus(true)          -- Set keyboard focus
ui:HasFocus()              -- Check focus (boolean)

Z-Order

ui:BringToFront()          -- Move to top of stack
ui:SendToBack()            -- Move to bottom of stack
ui:SetZOrder(100)          -- Set explicit z-order (higher = on top)

Size & Position

ui:SetSize(800, 600)       -- Set dimensions in pixels
ui:SetPosition(100, 100)   -- Set position from top-left
ui:SetFullscreen(true)     -- Fill entire viewport

Lifecycle

ui:Reload()                -- Refresh the page
ui:Destroy()               -- Remove and cleanup

Lua ↔ JavaScript Communication

CallEvent (Lua → JS)

Send data from Lua to JavaScript.

ui:CallEvent("UpdateHealth", 75)
ui:CallEvent("ShowNotification", "Welcome!", "info")
ui:CallEvent("SetPlayerData", { name = "John", score = 100 })
// JavaScript
Events.Subscribe("UpdateHealth", (health) => {
    document.getElementById("health-bar").style.width = health + "%";
});

Events.Subscribe("SetPlayerData", (data) => {
    document.getElementById("player-name").textContent = data.name;
});

Subscribe (JS → Lua)

Receive events from JavaScript.

ui:Subscribe("ButtonClicked", function(button_id)
    Log("Button clicked: " .. button_id)
end)
// JavaScript
document.getElementById("buy-btn").onclick = () => {
    Events.Call("ButtonClicked", "buy-btn");
};

ExecuteJS

Execute raw JavaScript code.

ui:ExecuteJS("document.body.style.backgroundColor = 'red'")
ui:ExecuteJS("updateScore(" .. score .. ")")

Unsubscribe

Remove a JavaScript event subscription.

ui:Unsubscribe("ButtonClicked")

Store Integration

WebUI integrates with the Store through event bridging. Subscribe to Store changes and forward them to JavaScript.

-- Bridge Store to JavaScript
local function BindStoreToJS(hud, storeKey, jsEvent)
    Store.Subscribe(storeKey, function(value)
        hud:CallEvent(jsEvent, value)
    end)
end

Client.Subscribe("Ready", function()
    local hud = WebUI.CreateAtScale("HUD", "hud/index.html")

    -- Bind Store keys to JS events
    BindStoreToJS(hud, "player.health", "UpdateHealth")
    BindStoreToJS(hud, "player.shield", "UpdateShield")
    BindStoreToJS(hud, "weapon.ammo", "UpdateAmmo")
end)

-- Server values flow to Store
Player.Subscribe("Ready", function(player)
    player:BindValue("health", function(val)
        Store.Set("player.health", val)
    end)
end)

Performance

WebUI.SetTargetFPS(60)              -- Set UI render target FPS
local fps = WebUI.GetTargetFPS()    -- Get current target FPS
WebUI.SetGPUAcceleration(true)      -- Enable GPU rendering
WebUI.SetEnabled(false)             -- Disable all WebUI rendering

Viewport Info

local width, height = WebUI.GetViewportSize()
local visible = WebUI.IsViewportVisible()

Complete Example

Lua Script

-- Client/ui.lua
local hud = nil

Client.Subscribe("Ready", function()
    hud = WebUI.CreateAtScale("HUD", "hud/index.html")
    hud:SetFullscreen(true)
    WebUI.ShowViewport(false)

    -- Receive from JS
    hud:Subscribe("ReadyClicked", function()
        Events.CallServer("PlayerReady", {})
    end)
end)

-- Bridge Store to JS
Store.Subscribe("player.health", function(value)
    if hud then hud:CallEvent("UpdateHealth", value) end
end)

Store.Subscribe("player.score", function(value)
    if hud then hud:CallEvent("UpdateScore", value) end
end)

-- Receive from server
Events.SubscribeRemote("GameMessage", function(data)
    if hud then
        hud:CallEvent("ShowMessage", data.text, data.duration)
    end
end)

HTML

<!-- games/my_game/Client/UI/hud/index.html -->
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="health-container">
        <div id="health-bar"></div>
        <span id="health-text">100</span>
    </div>
    <div id="score">Score: 0</div>
    <button id="ready-btn">Ready</button>

    <script src="script.js"></script>
</body>
</html>

JavaScript

// games/my_game/Client/UI/hud/script.js
Events.Subscribe("UpdateHealth", (health) => {
    document.getElementById("health-bar").style.width = health + "%";
    document.getElementById("health-text").textContent = health;
});

Events.Subscribe("UpdateScore", (score) => {
    document.getElementById("score").textContent = "Score: " + score;
});

document.getElementById("ready-btn").onclick = () => {
    Events.Call("ReadyClicked");
};

File Structure

games/my_game/
├── Client/
│   ├── ui.lua           # UI logic
│   └── UI/
│       ├── hud/
│       │   ├── index.html
│       │   ├── style.css
│       │   └── script.js
│       └── menu/
│           ├── index.html
│           ├── style.css
│           └── script.js
└── Server/
    └── init.lua

On this page