Skip to content
CyanideX edited this page Aug 6, 2026 · 3 revisions

Begin / End

Drop-in replacements for ImGui.Begin / ImGui.End. Handles window registration, grid snapping, animation, and collapsed-state tracking automatically — no separate Update() call needed.

Quick Start

local wu = GetMod("WindowUtils") or ImGui

registerForEvent("onDraw", function()
    if wu.Begin("My Window") then
        ImGui.Text("Hello")
    end
    wu.End()
end)

That's it. Grid snapping, animations, and collapse tracking all happen inside Begin/End. Works identically whether WindowUtils is installed or not — the or ImGui fallback passes calls straight through to native ImGui.

API

wu.Begin(windowName, ...)

Drop-in replacement for ImGui.Begin. Accepts the same arguments plus an optional trailing opts table.

-- Minimal
if wu.Begin("My Window") then ... end

-- With flags
if wu.Begin("My Window", ImGuiWindowFlags.NoResize) then ... end

-- With close button (pOpen)
local visible, open = wu.Begin("My Window", true)

-- With flags and close button
local visible, open = wu.Begin("My Window", true, ImGuiWindowFlags.NoResize)

-- With opts table
if wu.Begin("My Window", { skip = isDocked }) then ... end

Returns the same values as ImGui.Begin. If pOpen was passed, returns visible, pOpenOut.

wu.End()

Drop-in replacement for ImGui.End. Always call this after wu.Begin, regardless of whether the window is visible.

if wu.Begin("My Window") then
    -- content
end
wu.End()  -- always call End

Opts Table

Pass a table as the last argument to control per-call behavior:

Option Type Description
skip boolean Skip Update() this frame. Window stays registered but won't snap or animate. Only the literal value true skips. Useful when docking or embedding.
ignored boolean Mark window as permanently ignored on first call. No management, no grid snap, no browser entry. Written to disk (also sets locked).
pOpen boolean Register the window as having a close button (probeOverride) without passing pOpen as an argument. Applied on the first call only, and only when no probeOverride is already stored for that window. Ignored windows skip this.
-- Skip grid management when docked
if wu.Begin("Timeline", { skip = isDocked }) then ... end

-- Permanently ignore an overlay window
wu.Begin("##hitzone", { ignored = true })

Window Names and Stable IDs

WindowUtils supports ImGui's ### stable ID syntax for registration. First-call setup and the registry key on the ###id part, so a changing display label does not re-register the window or duplicate its browser entry.

-- Registration keys on "###mywin" no matter what the label says
local title = string.format("Settings (%d)###mywin", count)
if wu.Begin(title) then ... end
wu.End()

Geometry tracking is a different story. Grid snap state, per-window config, and the ignored/locked flags are keyed on the full name string you pass in, so a label that changes at runtime starts a fresh state entry each time it changes. If you rely on per-window config, animation state, or the intermod state API, keep the full window name constant and put the varying text somewhere else.

Window Tags

Append a tag to any window name to control how WindowUtils handles it. Tags work with both wu.Begin and raw ImGui.Begin, and inside ImGui's ## hidden ID syntax.

Tag Effect Equivalent opts
-wui Ignored - no management, no browser entry { ignored = true }
-wuo Close button registered (probeOverride) { pOpen = true }

Tags are the preferred approach for windows using raw ImGui.Begin. For wu.Begin, opts are equivalent and don't require changing the window name.

-- Raw ImGui.Begin - use tags
ImGui.Begin("##drag-wui")                    -- ignored
ImGui.Begin("Depth Selection##wb-wui")       -- ignored, visible title kept
ImGui.Begin("My Panel##wb-wuo")              -- probeOverride (close button)

-- wu.Begin - opts are equivalent
wu.Begin("##drag", { ignored = true })
wu.Begin("My Panel", { pOpen = true })

Tags are detected anywhere in the name, so they compose naturally with ## IDs. The visible title is unaffected.

Close Button

Pass true (or a boolean variable) as pOpen to get a close button. WindowUtils registers the window with hasCloseButton = true so the window browser handles it correctly.

local open = true

registerForEvent("onDraw", function()
    if not open then return end
    local _, stillOpen = wu.Begin("Panel", open)
    open = stillOpen
    if stillOpen then
        ImGui.Text("Content")
    end
    wu.End()
end)

Locking Windows

There is no dedicated lock function. A window becomes locked as a side effect of the calls that pin its state, so its browser entry is read-only:

wu.API.IgnoreWindow("##drag")            -- ignored + locked
wu.API.SetCloseButton("##overlay")       -- probeOverride + locked
wu.Begin("##drag", { ignored = true })   -- ignored + locked on first call
wu.Begin("Panel", { pOpen = true })      -- probeOverride + locked on first call

Locked windows appear under the "Locked" section in the browser with all controls disabled. ignored additionally means the window isn't managed or tracked at all.

Relationship to Update()

wu.Begin/wu.End is the preferred integration path and replaces manual Update() calls entirely. If you're using the manual pattern, don't mix it with wu.Begin on the same window.

For the manual pattern and its constraints, see the Developer Guide.

Clone this wiki locally