Skip to content

Sleek — The Legacy IMGUI UI System

Sleek is Unturned's original UI framework, predating the Glazier abstraction. It defines a tree of ISleekElement widgets positioned through a scale+offset coordinate system, with event delegates for interaction. The entire UI is rebuilt every frame — widgets are created, populated, drawn, and destroyed within the same update cycle, a pattern inherited from Unity's IMGUI paradigm.

Source code location: SDG.Glazier/Sleek.cs, GlazierElementBase.cs, SleekWrapper.cs, SleekWindow.cs, SleekBox.cs, SleekButton.cs, SleekLabel.cs, SleekScrollBox.cs

ISleekElement Interface

ISleekElement is the root of the entire widget hierarchy. Every UI element — boxes, buttons, labels, images, sliders, fields, scroll views — implements this interface. It defines:

Position and size use a dual-coordinate system of scale (0.0–1.0 fraction of parent) and offset (absolute pixel count):

csharp
float PositionOffset_X, PositionOffset_Y;  // Pixel offset from parent origin
float PositionScale_X, PositionScale_Y;     // Fraction of parent size
float SizeOffset_X, SizeOffset_Y;            // Pixel size adjustment
float SizeScale_X, SizeScale_Y;              // Fractional size of parent

The final position is parent_size * scale + offset. For example, an element with PositionScale_X = 0.5 and PositionOffset_X = -50 centers itself with a 50-pixel leftward adjustment.

Layout properties control automatic child arrangement:

  • UseManualLayout — enables manual scale/offset positioning (default true)
  • UseChildAutoLayout — set to ESleekChildLayout.Vertical or Horizontal for automatic stacking
  • ChildPerpendicularAlignment — Center, Top, or Bottom alignment for children
  • ExpandChildren — fills available space across children
  • ChildAutoLayoutPadding — gap between auto-laid-out children in pixels
  • IgnoreLayout — excludes an element from auto-layout calculations

Visibility and hierarchy:

  • IsVisible — hides without removing from the tree
  • Parent — read-only parent reference
  • AddChild, RemoveChild, RemoveAllChildren — tree manipulation
  • FindIndexOfChild, GetChildAtIndex, GetChildCount — child enumeration

Transform animation:

csharp
void AnimatePositionOffset(float x, float y, ESleekLerp lerp, float time);
void AnimatePositionScale(float x, float y, ESleekLerp lerp, float time);
void AnimateSizeOffset(float x, float y, ESleekLerp lerp, float time);
void AnimateSizeScale(float x, float y, ESleekLerp lerp, float time);

Each animate method uses an ESleekLerp (Accelerate, Decelerate, or Linear) over a duration in seconds. The ISleekElement.IsAnimatingTransform property and isTransformDirty flag track animation state.

Utility:

  • ViewportToNormalizedPosition — converts viewport coords to 0-1 normalized space
  • GetNormalizedCursorPosition — returns cursor position in 0-1 normalized space
  • GetAbsoluteSize — returns pixel size of the element
  • SetAsFirstSibling — reorders element to the top of its parent's children

GlazierElementBase — Abstract Implementation

GlazierElementBase is the concrete abstract base for all IMGUI-style elements. It implements ISleekElement and provides:

  • Field storage for all position/offset/scale properties with ValidateNotDestroyed guards
  • The complete transform animation engine with per-axis lerp fields:
    • Four sets of from/to/time/method fields for position offset, position scale, size offset, and size scale
    • Each axis pair has independent lerp tracking
  • isTransformDirty flag set whenever a position or size property changes
  • SideLabel support — creates a ISleekLabel attached to a specified side of the element

SleekWrapper — Widget Composition

SleekWrapper is a proxy class that wraps a single ISleekProxyImplementation (created by Glazier.Get().CreateProxyImplementation(this)). It delegates every ISleekElement method to the underlying implementation. This indirection allows composite widgets — such as SleekServer, SleekInventory, SleekCharacter — to inherit from SleekWrapper and compose multiple primitive elements without inheriting from a specific glazier implementation's base class.

Key design points:

  • GetProxyImplementation() returns the inner ISleekProxyImplementation for advanced access
  • OnUpdate() and OnDestroy() virtual methods called by the proxy during its lifecycle
  • ValidateNotDestroyed() conditional compile-time guard prevents use-after-free under VALIDATE_SLEEK_PROXY_USE_AFTER_DESTROY

SleekWindow — Root Element

SleekWindow extends SleekWrapper and serves as the root of the entire UI tree. It is assigned to Glazier.Get().Root. Every visible element is a descendant of this root.

SleekWindow manages cursor state:

csharp
public bool showCursor;
public bool isEnabled;
public bool drawCursorWhileDisabled;
public bool showTooltips;

The ShouldDrawCursor property gates cursor rendering. The isCursorLocked property implements a two-frame debounce to prevent macOS angle snap issues when re-locking the cursor. The OnUpdate() method sets Cursor.visible = false and toggles Cursor.lockState between Locked and None based on ShouldDrawCursor.

The constructor sets SizeScale_X = 1 and SizeScale_Y = 1, making the root fill the entire screen.

Interface Hierarchy for Primitive Widgets

The interface hierarchy builds on ISleekElement with specialized contracts:

  • ISleekLabel : ISleekElementText, FontStyle, TextAlignment, ESleekFontSize, TextColor, AllowRichText
  • ISleekBox : ISleekLabel, ISleekWithTooltip — adds BackgroundColor
  • ISleekButton : ISleekElement, ISleekLabel, ISleekWithTooltip — adds OnClicked/OnRightClicked events, BackgroundColor, IsClickable, IsRaycastTarget
  • ISleekScrollView : ISleekElementScaleContentToWidth/Height, ContentScaleFactor, ReduceWidthWhenScrollbarVisible, VerticalScrollbarVisibility
  • ISleekSlider : ISleekElementOrientation, Value, MinValue, MaxValue, OnValueChanged
  • ISleekToggle : ISleekElementValue, IsInteractable, OnValueChanged
  • ISleekField : ISleekElementText, PlaceholderText, MaxLength, IsMultiline, OnTextChanged, OnTextSubmitted
  • ISleekImage : ISleekElementTexture, TintColor, ShouldDestroyTexture
  • ISleekSprite : ISleekElementSprite, TintColor, DrawMethod (sliced, tiled, stretched)
  • ISleekConstraintFrame : ISleekElementESleekConstraint for aspect-ratio locking

Event Handling Pattern

Sleek uses C# events for user interaction. Widgets expose events as delegates:

csharp
public delegate void ClickedButton(ISleekElement button);
public delegate void ClickedMouse();
public delegate void MovedMouse(float x, float y);

Parent widgets subscribe to child events in the constructor or OnUpdate:

csharp
button.OnClicked += OnClickedButton;
toggle.OnValueChanged += OnValueToggled;

The Glazier implementation (IMGUI, uGUI, or UIToolkit) translates the underlying input system into these delegate invocations. This keeps the Sleek layer input-system-agnostic.

The Scale+Offset Coordinate System

The core positioning formula for any element is:

x = parent_width  * PositionScale_X + PositionOffset_X
y = parent_height * PositionScale_Y + PositionOffset_Y
width  = parent_width  * SizeScale_X + SizeOffset_X
height = parent_height * SizeScale_Y + SizeOffset_Y

This system has two major advantages:

  1. Resolution independence — Layouts defined in scale units (e.g., SizeScale=0.5) automatically adapt to any screen resolution
  2. Pixel-perfect adjustment — Offset values allow fine-tuning without affecting proportional layout

For example, a button centered horizontally with a fixed 200px width and 30px height would use:

  • PositionScale_X = 0.5, SizeOffset_X = -200, SizeScale_X = 0
  • SizeOffset_Y = 30

The UseManualLayout = false mode switches to auto-layout, where only SizeOffset_X and SizeOffset_Y are meaningful (overriding auto-calculated sizes through UseWidthLayoutOverride and UseHeightLayoutOverride).