Skip to content

Glazier — The UI Abstraction Layer

Glazier is the UI abstraction layer introduced to decouple Unturned's UI code from Unity's rendering backend. It defines a factory interface (IGlazier) that creates UI elements without exposing their underlying implementation, allowing the same Sleek widget code to run on IMGUI, uGUI (Canvas), or UIToolkit (UIElements) without modification.

Source code location: Glazier/GlazierBase.cs, GlazierFactory.cs, GlazierResources.cs, SDG.Glazier/Glazier.cs, Glazier_IMGUI/Glazier_IMGUI.cs, Glazier_uGUI/Glazier_uGUI.cs

The IGlazier Interface

IGlazier is the factory contract that every backend must implement. It defines creation methods for every Sleek widget type:

csharp
public interface IGlazier
{
    ISleekBox CreateBox();
    ISleekButton CreateButton();
    ISleekElement CreateFrame();
    ISleekConstraintFrame CreateConstraintFrame();
    ISleekImage CreateImage();
    ISleekImage CreateImage(Texture texture);
    ISleekSprite CreateSprite();
    ISleekSprite CreateSprite(Sprite sprite);
    ISleekLabel CreateLabel();
    ISleekScrollView CreateScrollView();
    ISleekSlider CreateSlider();
    ISleekField CreateStringField();
    ISleekToggle CreateToggle();
    ISleekUInt8Field CreateUInt8Field();
    ISleekUInt16Field CreateUInt16Field();
    ISleekUInt32Field CreateUInt32Field();
    ISleekInt32Field CreateInt32Field();
    ISleekFloat32Field CreateFloat32Field();
    ISleekFloat64Field CreateFloat64Field();
    ISleekProxyImplementation CreateProxyImplementation(SleekWrapper owner);
    SleekWindow Root { get; set; }
}

Each method returns an interface type — calling code never references the concrete implementation class. This enables full backend swapping.

Capability Flags

The interface exposes boolean capability flags that let Sleek code adapt to backend limitations:

PropertyIMGUIuGUIUIToolkitPurpose
SupportsDepthfalsetruetrueElement layering and focus routing
SupportsRichTextAlphafalsetruetrueRich text color alpha multiplication
SupportsAutomaticLayoutfalsetruetrueVertical/horizontal auto-layout
SupportsTilingSpritetruetruefalseTiled sprite rendering
ShouldGameProcessInputInput blocking while interacting with UI
ShouldGameProcessKeyDownKeyboard processing while text fields are focused

The SupportsRichTextAlpha flag is particularly important: in IMGUI, rich text color tags do not multiply alpha with the label color, so UI code must branch on this.

GlazierBase — Shared Backend Logic

GlazierBase is an abstract MonoBehaviour that provides common functionality shared by all backends:

Input processing guard:

csharp
public bool ShouldGameProcessInput =>
    GUIUtility.hotControl == 0 && !EventSystem.current.IsPointerOverGameObject();

Key-down processing:

csharp
public virtual bool ShouldGameProcessKeyDown
{
    get
    {
        GameObject selected = EventSystem.current?.currentSelectedGameObject;
        if (selected == null) return true;
        InputField inputField = selected.GetComponent<InputField>();
        if (inputField != null) return !inputField.isFocused;
        TMP_InputField tmpInputField = selected.GetComponent<TMP_InputField>();
        if (tmpInputField != null) return !tmpInputField.isFocused;
        return true;
    }
}

This ensures hotkeys like WASD or inventory shortcuts are suppressed while typing in a text field. The implementation handles both legacy Unity InputField and TextMeshPro TMP_InputField for plugin compatibility.

Debug overlay (UpdateDebugString): Builds the HUD debug string including FPS, ping, connection timeout warning, freecam state, and per-system loading indicators. The string is color-coded: green during normal operation, red when the server connection is timing out.

Scroll view sensitivity: A configurable multiplier via the -ScrollViewSensitivity command-line flag, defaulting to 1.0x.

GlazierFactory — Backend Selection

GlazierFactory.Create() selects the rendering backend through a priority chain:

  1. Unity Editor override — checks EditorPrefs.GetInt("Glazier") for values 1 (IMGUI), 2 (uGUI), 3 (UIToolkit)
  2. Command-line override — parses the -Glazier argument for "IMGUI", "uGUI", or "UIToolkit"
  3. Default — falls back to Glazier_uGUI
csharp
public static void Create()
{
    // Editor override
    // Command-line override
    Glazier.instance = Glazier_uGUI.CreateGlazier();
}

The dedicated server raises a NotSupportedException — Glazier should not be used on headless server builds.

IMGUI Backend

Glazier_IMGUI is the original rendering backend, wrapping Unity's immediate-mode GUI system. Each factory method creates an IMGUI- specific widget (e.g., GlazierBox_IMGUI, GlazierButton_IMGUI). IMGUI widgets draw themselves every frame using GUI.Box, GUI.Button, GUI.Label, etc.

Characteristics:

  • No depth sorting — SupportsDepth = false
  • No automatic layout — SupportsAutomaticLayout = false
  • No rich text alpha — SupportsRichTextAlpha = false
  • Elements are drawn in registration order with no z-buffer
  • Used primarily for the level editor and legacy UI paths

uGUI Backend (Default)

Glazier_uGUI is the primary rendering backend. It creates Unity Canvas-based UI elements with GameObject pooling for performance:

csharp
public ISleekBox CreateBox()
{
    GlazierBox_uGUI box = new GlazierBox_uGUI(this);
    elements.Add(box);
    GlazierBox_uGUI.BoxPoolData poolData = ClaimElementFromPool(boxPool);
    if (poolData == null)
        box.ConstructNew();
    else
        box.ConstructFromBoxPool(poolData);
    box.SynchronizeTheme();
    box.SynchronizeColors();
    ValidateNewElement(box);
    return box;
}

Element pooling: The uGUI backend maintains pools per element type (boxPool, buttonPool, framePool, imagePool, labelPool, togglePool, etc.). When an element is destroyed, its GameObject components are returned to the pool. When a new element is requested, the pool is checked first to avoid allocation.

Pooling flow:

  1. ClaimElementFromPool(pool) — tries to reuse an existing entry
  2. If miss, ConstructNew() — instantiates a new GameObject with the required components
  3. If hit, ConstructFromPool(poolData) — reparents and reactivates the pooled GameObject
  4. SynchronizeTheme() — applies current theme colors
  5. SynchronizeColors() — applies per-element color overrides
  6. ValidateNewElement(box) — runs debug validation checks

Theme support: The SynchronizeTheme method reads from GlazierResources and applies the active UI theme. Color synchronization is separate from theme synchronization for fine-grained control.

UIToolkit Backend

Glazier_UIToolkit uses Unity's UI Toolkit (UIElements). As of 2024, this backend is experimental with known limitations:

  • SupportsTilingSprite = false — tiled sprite backgrounds do not work, affecting the news feed background (public issue #4800)
  • Element construction follows the same factory pattern but uses VisualElement instead of GameObject
  • UIToolkit provides better styling separation and CSS-like layout

Image and Sprite Management

Glazier provides separate interfaces for texture-based and sprite-based images:

ISleekImage — wraps a Texture2D with tint color and optional auto-destruction of the texture. Used for dynamic textures like web images and player portraits.

ISleekSprite — wraps a UnityEngine.Sprite with draw method selection (sliced, tiled, stretched) and tint color. Used for UI chrome, button backgrounds, and themed elements.

GlazierResources provides a shared white 1x1 pixel texture (Materials/Pixel) used by the IMGUI backend for solid-color images. The uGUI backend can use this same texture via ISleekImage for backwards compatibility.

Text Rendering

Labels are created through ISleekLabel and support:

  • FontStyle — Normal, Bold, Italic, BoldAndItalic
  • TextAnchor — alignment (UpperLeft through LowerRight)
  • ESleekFontSize — predefined size tiers
  • ETextContrastContext — shadow/outline style for readability against varying backgrounds
  • AllowRichText — enables <color>, <b>, <i> tags
  • SleekColor TextColor — color with theme-aware alpha

When SupportsRichTextAlpha is true (uGUI/UIToolkit), color tags with alpha values multiply against the label's TextColor. When false (IMGUI), color tag alpha is ignored.