DreamGUI
The .dui Language

use

Merging a library, giving a component or a class a short name, putting a library under a namespace, aliases that travel with their library, and the older @Name.

use makes another file, or a class, available to this one. There are four forms:

use "UI/Library.dui"                     // a library, merged
use "UI/Components/Row.dui" as Row       // a component, by a short name
use /Game/UI/WBP_Slider as Slider        // a class with no .dui, by a short name
use "UI/NieR_Common.dui" as nier         // a library, under a namespace

VerticalBox Root {
    Row Audio : Wide { Label = "Audio" }
    Slider Volume { }
    nier.Row Video : nier.Label { Label = "Video" }
}

A file path is quoted and spelled as a Source File is (relative to a DUI/ root, Plugin.X:…, or absolute; see the Overview); a class path is not quoted. Which of the forms a use … as is depends on whether it names a file or a class, and whether that file has a root.

Merged: use "…"

A plain use of a file brings in its styles, its resources and the component aliases it declares. The file's own use lines come along, so libraries layer. A name this file declares shadows an imported one.

// DUI/UI/Library.dui — a library: no root node
resources {
    Color Ink = #E6E9F0
}
style Wide { AnchorData.SizeDelta = (1100, 48) }
style Caption {
    FontSize = 18
    Color    = @Ink
}
// DUI/UI/About.dui
class /Game/UI/WBP_About
use "UI/Library.dui"

VerticalBox Root {
    Text Heading : Caption { Text = "About" }
    Text Body : Caption { Color = @Ink  Text = "Version 1.0.0" }
}
  • Imported resources become variables of this class too, visible to a graph and the Class Defaults panel. Imported styles do not: a style is a bag of values applied by name.
  • Timelines are not merged by use: a timeline compiles into an object on this class's tree and a class member variable named after it, so importing one would mean two classes owning one animation.
  • A library reached two ways (A uses B and C, both of which use D) is merged once, silently: writing use twice for a library you reach two ways is not a mistake.
  • An import that cannot be read, does not parse, or comes back around to a file already being imported (a cycle) is DUI2012.

A component: use "…" as Row

use "…" as Row on a file that has a root node names that file's class, and takes nothing else from it: a screen does not borrow a component's styles.

use "UI/Components/Row.dui" as Row

VerticalBox Root {
    Spacing = 29
    Row Audio { Label = "Audio" }
    Row Video { Label = "Video" }
}

Row is then a node type, and Row Audio { … } is an instance whose lines set that class's properties (see Nodes and values).

Where the class comes from:

  • The file's class line, when it has one.
  • Otherwise the editor finds the Blueprint whose Source File the file is. Without the editor — in a commandlet — there is nobody to ask, and that is DUI5018; a class line is the fix.

Only the file's header is read: whether it has a root, and what its class line says. Its own use lines are not followed. That is not only a saving: a library that names its components (use "Row.dui" as Row) is very often also what those components style themselves from (use "Common.dui" inside Row.dui), and following that line would walk straight back into the library and report a cycle that is not there. A component's class is all an importer takes from it, and its class does not depend on its styles.

A file that names itself as a component is DUI2012. The component file is still recorded as one of this file's imports, so a screen is recompiled when the component's class line moves.

A class: use /Game/… as Slider

use /Game/UI/WBP_Slider as Slider

Widget Root {
    + VerticalBox { }
    Slider Volume { }
}

This names a class that has no .dui behind it. The as is required here: a class path without one is DUI2015.

A namespace: use "…" as nier

use "…" as nier on a file with no root (a library) is a namespace: everything the library declares or brought in is entered as nier.X.

KindWritten
a style: nier.Label
a resource@nier.Ink
a component aliasnier.Row

Two libraries that both say Label can then be used side by side. A style that came in under a namespace still finds its own library's names: Color = @Ink written in the library means the library's Ink, not this file's.

// DUI/UI/Settings.dui
use "UI/Library.dui" as lib
use "UI/NieR_Common.dui" as nier

VerticalBox Root {
    Text Heading : lib.Caption { Text = "Settings" }
    Text Note : nier.Label { Color = @nier.Ink  Text = "Two libraries, side by side" }
}

An ns. that no use … as ns of this file declares is DUI3021. A plain use of a library that itself uses a namespace brings that namespace along: @pal.Ink resolves here exactly as it did in the library that declared pal.

Re-export: a library's use … as

A library's own use … as Row lines travel with it. A library that names a family of components gives every screen that uses it those names — Row after a plain use, nier.Row after use … as nier:

// DUI/UI/NieR_Common.dui
use "UI/Components/NieR_Row.dui" as Row
use "UI/Components/NieR_Tab.dui" as Tab

style ListRow { AnchorData.SizeDelta = (1100, 48) }
// DUI/UI/NieR_Menu.dui
use "UI/NieR_Common.dui"

Widget Root {
    + VerticalBox { Spacing = 8 }
    Row Item_0 : ListRow { Label = "Warped Wire" }
    Tab Weapons { Label = "Weapons" }
}

A family of components is then named once, in the library that styles it, and no screen writes an asset path.

Rules for the name

The name after as:

  • is one word and not a keyword (DUI2015, which is also a use … as with no name);
  • is not the name of a tag or a container (DUI3018) — an alias can never change what Text or VerticalBox means;
  • is given once per file (DUI3017).

An alias that names no class — no class line and no Blueprint for the file, or a path that loads nothing — is DUI5018. In VS Code an unknown component type (DUI3003) offers a quick fix adding use "…" as X when exactly one component file of that name exists in the workspace.

@Name: the older spelling

Before use … as, a component's short name was an Asset entry of a resources block:

resources {
    Asset Row = /Game/UI/WBP_Row
}

VerticalBox Root {
    @Row Audio { Label = "Audio" }
    @Row Video { Label = "Video" }
}

The entry may be this file's or one a use brought in, so it too can be named once in a library. A missing entry is DUI4007, one that is not an Asset DUI4008, one that names no user widget DUI5006. The spelling keeps working; use … as says the same with less and is the one to reach for.

On this page