Table of Contents

Canvas, the host and the element tree

Everything IcyUI draws lives on a Canvas: a surface the size of your game's window that lays out its elements, draws them every frame and routes mouse, keyboard, gamepad and touch input to them. UseIcyUI() creates the host that connects canvases to your engine and gives you the first canvas.

The host

UseIcyUI() returns the engine's host: MonoGameIcyHost or StrideIcyHost. Both are an IIcyHost:

The host pumps input and follows the display scale every frame. On MonoGame it's a game component that draws during base.Draw(), after your own drawing; on Stride it draws through the graphics compositor, after the scene. Other code reaches the same host with GetIcyHost() (or GetIcyCanvas() for the main canvas) on the game.

A later canvas in Canvases draws on top of an earlier one. A second canvas is useful for a HUD that stays above menus, or a debug layer:

// A second canvas for a HUD, drawn above the main one; a background canvas at index 0 would draw below.
public static Canvas AddHudCanvas(IIcyHost ui)
{
    var hud = new Canvas(ui.Configuration);
    ui.Canvases.Add(hud);
    return hud;
}

The element tree

A canvas holds root elements (Add(UIElement), or LoadMarkup for a markup file). Panels and controls hold children, so the whole UI is a tree. Each element knows its Parent; a root's parent is null, and it belongs to the canvas.

  • Drawing order: children draw after their parent, in order; ZIndex moves an element above or below its siblings.
  • Overlays: popups, dropdown lists, tooltips and dialogs go to the canvas's Overlays, which draw above every root element and receive input first.
  • Visibility: IsVisible hides an element and its children and stops their input, but they keep their space in the layout; Opacity fades them (at 0 they aren't drawn or hit); IsHitTestVisible set to false lets clicks pass through.

UI input and game input

The canvas takes the input that's meant for the UI. Your game should ignore a click that landed on a button: check IsMouseOverGUI before acting on the mouse.

// In your game's update: don't fire when the player clicks a button.
public static bool ShouldFire(IIcyHost ui, bool mousePressed) => mousePressed && !ui.MainCanvas.IsMouseOverGUI;

Which element has keyboard and gamepad focus is FocusedElement; see Input, focus and navigation.

Pitfalls

  • An element belongs to one parent. Adding an element that is still in a panel, a border, a control's content or the canvas throws InvalidOperationException. Remove it from there first (Children.Remove, Content = null, Canvas.Remove), then add it somewhere else.
  • Elements created in code have no theme until they're attached. The theme's styles apply when an element joins a canvas, so read Template or theme colors after Add, not before.
  • Hidden still takes space. To take an element out of the layout, remove it from its panel; set IsVisible back when it should only reappear in place.
  • Draw your own content before the UI. On MonoGame, anything you draw after base.Draw() covers the UI.

See also