Skip to content

Chapter 3.2: Layout File Format (.layout)

Home | << Previous: Widget Types | Layout File Format | Next: Sizing & Positioning >>


Podstawowa struktura

A .layout file defines a tree of widgets. Every file has exactly one root widget, which contains nested children.

WidgetTypeClass WidgetName {
 attribute value
 attribute "quoted value"
 {
  ChildWidgetTypeClass ChildName {
   attribute value
  }
 }
}

Key rules:

  1. The root element is always a single widget (typically FrameWidgetClass).
  2. Widget type names use the layout class name, which always ends with Class (e.g., FrameWidgetClass, TextWidgetClass, ButtonWidgetClass).
  3. Each widget has a unique name following its type class.
  4. Attributes are key value pairs, one per line.
  5. Attribute names containing spaces must be quoted: "text halign" center.
  6. String values are quoted: text "Hello World".
  7. Numeric values are unquoted: size 0.5 0.3.
  8. Children are nested inside { } blocks after the parent's attributes.

Referencja atrybutow

Positioning & Sizing

AttributeValuesDescription
positionx yWidget position (proportional 0-1 or pixel values)
sizew hWidget dimensions (proportional 0-1 or pixel values)
halignleft_ref, center_ref, right_refHorizontal alignment reference point
valigntop_ref, center_ref, bottom_refVertical alignment reference point
hexactpos0 or 10 = proportional X position, 1 = pixel X position
vexactpos0 or 10 = proportional Y position, 1 = pixel Y position
hexactsize0 or 10 = proportional width, 1 = pixel width
vexactsize0 or 10 = proportional height, 1 = pixel height
fixaspectfixwidth, fixheightMaintain aspect ratio by constraining one dimension
scaled0 or 1Scale with DayZ UI scaling setting
priorityintegerZ-order (higher values render on top)

The hexactpos, vexactpos, hexactsize, and vexactsize flags are the most important attributes in the entire layout system. They control whether each dimension uses proportional (0.0 - 1.0 relative to parent) or pixel (absolute screen pixels) units. See 3.3 Sizing & Positioning for a thorough explanation.

Visual Attributes

AttributeValuesDescription
visible0 or 1Initial visibility (0 = hidden)
colorr g b aColor as four floats, each 0.0 to 1.0
stylestyle namePredefined visual style (e.g., Default, Colorable)
draggable0 or 1Widget can be dragged by the user
clipchildren0 or 1Clip child widgets to this widget's bounds
inheritalpha0 or 1Children inherit this widget's alpha value
keepsafezone0 or 1Keep widget within screen safe zone

Behavioral Attributes

AttributeValuesDescription
ignorepointer0 or 1Widget ignores mouse input (clicks pass through)
disabled0 or 1Widget is disabled
"no focus"0 or 1Widget cannot receive keyboard focus

Text Attributes

These apply to TextWidgetClass, RichTextWidgetClass, MultilineTextWidgetClass, ButtonWidgetClass, and other text-bearing widgets.

AttributeValuesDescription
text"string"Default text content
font"path/to/font"Font file path
"text halign"left, center, rightHorizontal text alignment within the widget
"text valign"top, center, bottomVertical text alignment within the widget
"bold text"0 or 1Bold rendering
"italic text"0 or 1Italic rendering
"exact text"0 or 1Use exact pixel font size instead of proportional
"exact text size"integerFont size in pixels (requires "exact text" 1)
"size to text h"0 or 1Resize widget width to fit text
"size to text v"0 or 1Resize widget height to fit text
"text sharpness"floatText rendering sharpness
wrap0 or 1Enable word wrapping

Image Attributes

These apply to ImageWidgetClass.

AttributeValuesDescription
image0"set:name image:name"Primary image from an imageset
modeblend, additive, stretchImage blend mode
"src alpha"0 or 1Use the source alpha channel
stretch0 or 1Stretch image to fill widget
filter0 or 1Enable texture filtering
"flip u"0 or 1Flip image horizontally
"flip v"0 or 1Flip image vertically
"clamp mode"clamp, wrapTexture edge behavior
"stretch mode"stretch_w_h, etc.Stretch mode

Spacer Attributes

These apply to WrapSpacerWidgetClass and GridSpacerWidgetClass.

AttributeValuesDescription
PaddingintegerInner padding in pixels
MarginintegerSpace between child items in pixels
"Size To Content H"0 or 1Resize width to match children
"Size To Content V"0 or 1Resize height to match children
content_halignleft, center, rightChild content horizontal alignment
content_valigntop, center, bottomChild content vertical alignment
ColumnsintegerGrid columns (GridSpacer only)
RowsintegerGrid rows (GridSpacer only)

Button Attributes

AttributeValuesDescription
switchtoggleMakes the button a toggle (stays pressed)
stylestyle nameVisual style for the button

Slider Attributes

AttributeValuesDescription
"fill in"0 or 1Show a filled track behind the slider handle
"listen to input"0 or 1Respond to mouse input

Scroll Attributes

AttributeValuesDescription
"Scrollbar V"0 or 1Show vertical scrollbar
"Scrollbar H"0 or 1Show horizontal scrollbar

Integracja ze skryptami

The scriptclass Attribute

The scriptclass attribute binds a widget to an Enforce Script class. When the layout is loaded, the engine creates an instance of that class and calls its OnWidgetScriptInit(Widget w) method.

FrameWidgetClass MyPanel {
 size 1 1
 scriptclass "MyPanelHandler"
}

The script class must inherit from Managed and implement OnWidgetScriptInit:

c
class MyPanelHandler : Managed
{
    Widget m_Root;

    void OnWidgetScriptInit(Widget w)
    {
        m_Root = w;
    }
}

The ScriptParamsClass Block

Parameters can be passed from the layout to the scriptclass via a ScriptParamsClass block. This block appears as a second { } child block after the widget's children.

ImageWidgetClass Logo {
 image0 "set:dayz_gui image:DayZLogo"
 scriptclass "Bouncer"
 {
  ScriptParamsClass {
   amount 0.1
   speed 1
  }
 }
}

The script class reads these parameters in OnWidgetScriptInit by using the widget's script param system.

DabsFramework ViewBinding

In mods that use DabsFramework MVC, the scriptclass "ViewBinding" pattern connects widgets to a ViewController's data properties:

TextWidgetClass StatusLabel {
 scriptclass "ViewBinding"
 "text halign" center
 {
  ScriptParamsClass {
   Binding_Name "StatusText"
   Two_Way_Binding 0
  }
 }
}
ParamDescription
Binding_NameName of the ViewController property to bind to
Two_Way_Binding1 = UI changes push back to the controller
Relay_CommandFunction name on the controller to call when the widget is clicked/changed
Selected_ItemProperty to bind the selected item to (for lists)
Debug_Logging1 = enable verbose logging for this binding

Zagniezdzanie potomkow

Children are placed inside a { } block after the parent's attributes. Multiple children can exist in the same block.

FrameWidgetClass Parent {
 size 1 1
 {
  TextWidgetClass Child1 {
   position 0 0
   size 1 0.1
   text "First"
  }
  TextWidgetClass Child2 {
   position 0 0.1
   size 1 0.1
   text "Second"
  }
 }
}

Children are always positioned relative to their parent. A child with position 0 0 and size 1 1 (proportional) fills its parent completely.


Kompletny przyklad z adnotacjami

Here is a fully annotated layout file for a notification panel -- the kind of UI you might build for a mod:

// Root container -- invisible frame that covers 30% of screen width
// Centered horizontally, positioned at top of screen
FrameWidgetClass NotificationPanel {

 // Start hidden (script will show it)
 visible 0

 // Don't block mouse clicks on things behind this panel
 ignorepointer 1

 // Blue tint color (R=0.2, G=0.6, B=1.0, A=0.9)
 color 0.2 0.6 1.0 0.9

 // Position: 0 pixels from left, 0 pixels from top
 position 0 0
 hexactpos 1
 vexactpos 1

 // Size: 30% of parent width, 30 pixels tall
 size 0.3 30
 hexactsize 0
 vexactsize 1

 // Center horizontally within parent
 halign center_ref

 // Children block
 {
  // Text label fills the entire notification panel
  TextWidgetClass NotificationText {

   // Also ignore mouse input
   ignorepointer 1

   // Position at origin relative to parent
   position 0 0
   hexactpos 1
   vexactpos 1

   // Fill parent completely (proportional)
   size 1 1
   hexactsize 0
   vexactsize 0

   // Center the text both ways
   "text halign" center
   "text valign" center

   // Use a bold font
   font "gui/fonts/Metron-Bold"

   // Default text (will be overridden by script)
   text "Notification"
  }
 }
}

And here is a more complex example -- a dialog with a title bar, scrollable content, and a close button:

WrapSpacerWidgetClass MyDialog {
 clipchildren 1
 color 0.7059 0.7059 0.7059 0.7843
 size 0.35 0
 halign center_ref
 valign center_ref
 priority 998
 style Outline_1px_BlackBackground
 Padding 5
 "Size To Content H" 1
 "Size To Content V" 1
 content_halign center
 {
  // Title bar row
  FrameWidgetClass TitleBarRow {
   size 1 26
   hexactsize 0
   vexactsize 1
   draggable 1
   {
    PanelWidgetClass TitleBar {
     color 0.4196 0.6471 1 0.9412
     size 1 25
     style rover_sim_colorable
     {
      TextWidgetClass TitleText {
       size 0.85 0.9
       text "My Dialog"
       font "gui/fonts/Metron"
       "text halign" center
       "text valign" center
      }
      ButtonWidgetClass CloseBtn {
       size 0.15 0.9
       halign right_ref
       text "X"
      }
     }
    }
   }
  }

  // Scrollable content area
  ScrollWidgetClass ContentScroll {
   size 0.97 235
   hexactsize 0
   vexactsize 1
   "Scrollbar V" 1
   {
    WrapSpacerWidgetClass ContentItems {
     size 1 0
     hexactsize 0
     "Size To Content V" 1
    }
   }
  }
 }
}

Najczestsze bledy

  1. Zapomnienie o przyrostku Class -- W layoutach pisz TextWidgetClass, nie TextWidget.
  2. Mieszanie wartosci proporcjonalnych i pikselowych -- Jesli hexactsize 0, wartosci rozmiaru sa proporcjonalne 0.0-1.0. Jesli hexactsize 1, sa to wartosci pikselowe. Uzycie 300 w trybie proporcjonalnym oznacza 300x szerokosc rodzica.
  3. Brak cudzyslowow w wieloslownych atrybutach -- Pisz "text halign" center, nie text halign center.
  4. Umieszczenie ScriptParamsClass w zlym bloku -- Musi byc w oddzielnym bloku { } po bloku dzieci, nie wewnatrz niego.

Najlepsze praktyki

  • Zawsze ustawiaj wszystkie cztery flagi exact (hexactpos, vexactpos, hexactsize, vexactsize) jawnie na kazdym widgecie. Poleganie na domyslnych wartosciach prowadzi do niejednoznacznych layoutow, ktore sie psuja przy zmianie struktury rodzica.
  • Uzywaj scriptclass oszczednie -- tylko na widgetach, ktore naprawde potrzebuja zachowania sterowanego skryptem. Nadmierne wiazanie dodaje narzut inicjalizacji.
  • Nazywaj widgety opisowo (PlayerListScroll, TitleBarClose) zamiast generycznie (Frame1, btn). Kod skryptowy uzywa FindAnyWidget() po nazwie, a kolizje powoduja ciche awarie.
  • Utrzymuj pliki layout ponizej 200 linii. Dziel zlezone UI na wiele plikow .layout ladowanych za pomoca CreateWidgets() i laczonych programowo z rodzicem.
  • Zawsze umieszczaj wieloslowne nazwy atrybutow w cudzyslowach ("text halign", "Size To Content V"). Niecytowane wieloslowne atrybuty cicho zawodza bez bledu.

Teoria vs praktyka

Co dokumentacja mowi w porownaniu z tym, jak rzeczy faktycznie dzialaja w czasie wykonania.

KonceptTeoriaRzeczywistosc
Inicjalizacja scriptclassOnWidgetScriptInit jest wywolywana przy ladowaniu layoutuJesli klasa nie dziedziczy z Managed lub ma blad w konstruktorze, widget sie laduje, ale handler jest cicho null
ScriptParamsClassParametry przekazuja dowolne dane do klas skryptowychNiezawodnie dzialaja tylko wartosci tekstowe i liczbowe; zagniezdzone obiekty lub tablice nie sa obslugiwane
Atrybut colorCztery floaty 0.0-1.0 (RGBA)Niektore typy widgetow ignoruja kanal alfa lub wymagaja inheritalpha 1 na rodzicu dla propagacji przezroczystosci
Domyslne atrybutyNieudokumentowane atrybuty uzywaja domyslnych wartosci silnikaDomyslne wartosci roznia sie w zaleznosci od typu widgetu
"no focus"Zapobiega fokusowi klawiaturyZapobiega rowniez wyborowi gamepadem, co moze zepsuc nawigacje kontrolerem jesli ustawione na interaktywnych widgetach

Kompatybilnosc i wplyw

  • Multi-Mod: Pliki layout sa izolowane per mod -- brak bezposrednich konfliktow. Jednak nazwy scriptclass musza byc globalnie unikalne. Dwa mody uzywajace scriptclass "PanelHandler" spowoduja ciche niepowodzenie jednego z nich.
  • Wydajnosc: Kazdy widget w layoucie jest prawdziwym obiektem silnika. Layouty z 500+ widgetami powoduja mierzalne spadki klatek. Dla duzych list preferuj programowy pooling.
  • Wersja: Format layoutu jest stabilny od DayZ 1.0. Blok ScriptParamsClass i scriptclass ViewBinding zostaly dodane przez DabsFramework i nie sa funkcjami vanilla.

Zaobserwowane w prawdziwych modach

WzorzecModSzczegoly
scriptclass "ViewBinding" z ScriptParamsClassDabsFramework / DayZ EditorDwukierunkowe wiazanie danych miedzy layoutami i ViewControllerami przez parametr Binding_Name
WrapSpacerWidgetClass jako root dialoguCOT, ExpansionUmozliwia Size To Content V/H dla automatycznego rozmiaru dialogow wokol dynamicznej zawartosci
Osobny .layout na wiersz listyVPP Admin ToolsKazdy wiersz gracza jest samodzielnym layoutem ladowanym do WrapSpacer, umozliwiajacym ponowne uzycie i pooling
priority 998-999 dla nakladek modalnychDabsFramework, COTZapewnia, ze dialogi renderuja sie nad wszystkimi innymi elementami UI

Nastepne kroki

Released under CC BY-SA 4.0 | Code examples under MIT License