The widget designer
The DreamUI Designer, rebuilt against UMG's — picking by rect, resize handles and the anchor medallion, marquee selection and drag-to-reparent, the palette, undo, the source-file menu, event routes, and what it can and cannot change on a class backed by a .dui.
Opening a Dream Widget Blueprint opens the DreamUI Designer. It has two modes: Designer (the canvas, palette, hierarchy, details panel and animations) and Graph (the Blueprint event graph). The designer edits a preview instance of the class and writes back to the class itself, so there is no apply step and no per-instance override list to reconcile.
The designer is verified by tests, not by eye. Its gestures are covered by automation tests (the Designer
preset), but nobody has walked every corner of it by hand. Expect rough edges, and report them.
Gestures on the canvas
The designer was reviewed against UMG's widget designer. Added since upstream:
- Picking by rect. A click hits a widget's rect, not its rendered triangles. Layout-only panels have no mesh, so a raycast could never hit them, which upstream left them unclickable and undroppable; picking by rect is what fixes that.
- Hover feedback: the widget under the pointer is outlined.
- Per-axis resize handles, and the anchor medallion, which shows the selected widget's anchors on the canvas.
- Marquee selection: drag a box over empty space to select the widgets in it.
- Drag to reparent on the canvas: drag a widget into another container.
- Content Browser drops: drag assets straight onto the design surface.
- Undo: every designer gesture is one undo step, with create, paste and drop covered.
- Snapping and the grid: the toolbar's Snap switch and grid size; snapping guides while dragging.
- Align and distribute: the Arrange menu lines selected siblings up along an edge or centre (two or more selected) or evens out the gaps between them (three or more).
The hierarchy panel's context menu has Wrap With... (group the selection under a new container inserted at its position; the widgets keep their layout), Unwrap (take a widget out from between its parent and its children, which keep their order and land where it stood), Replace With... (swap the panel arranging the children — unlike UMG, the widget's own name, place, slot, components and children all stay put; only the layout container changes), Show / Hide in Designer, Lock / Unlock, Find References, Focus Selection (what the F key does), and Reveal in VS Code.
The palette
The palette lists what can be placed: primitive widgets, layout containers, the control library, and the project's widget Blueprints.
- Favourites: mark the entries you use; the favourites group comes first.
- Search: the search box filters entries, with every group expanded while it does.
The viewport toolbar
| Item | What it does |
|---|---|
| Screen Size | The device resolution previewed; Flip Orientation swaps width and height, Show Resolution Guides overlays common resolutions |
| Size Rule | Custom: the canvas is the resolution picked or typed; Fill Screen: the canvas is the viewport, one design unit per pixel; Desired: size the canvas to what the root's panel measures, for authoring a tooltip-sized widget at its own size |
| Zoom | Zoom to Fit frames the whole canvas (F frames the selection), Zoom 1:1 is one design unit per screen pixel |
| Rulers, Guides, Layout Debug | Rulers; snapping guides; the selected widget's measure / arrange / slot / clipping diagnostics |
| Safe Zone | Draw the platform's title-safe area (a desktop shows one only with r.DebugSafeZone.TitleRatio) |
| Respect Locks | Switch it off to select and drag a locked widget without unlocking it |
| Designer Chrome | Switch off the canvas boundary, outlines, handles, guides and every other overlay to see the widget alone |
| Preview DPI | Shrink the canvas by the project's DPI curve, previewing the application scale Slate will really apply |
| Preview Language | Resolve the preview's text in another culture, like UMG's Localization Preview; switched off when the designer closes |
| Screen Space / Canvas Eye | Build the preview the way play builds it, as a screen-space overlay canvas (which a declared perspective needs); stand the 3D view's camera where the canvas's own virtual camera stands |
Source files: classes backed by a .dui
A class's hierarchy can come from a .dui file. The DreamUI Source dropdown on the toolbar handles it:
| Entry | What it does |
|---|---|
| Create Source File... | Writes a starter .dui (a root plus one centred label), points the class at it and compiles. Offered only while the class has none |
| Set Source File... | Pick an existing .dui as the class's hierarchy, then recompile |
| Open in Default Editor | Open the file in whatever the system opens .dui files with |
| Show in Explorer | Select the file in the file browser |
| Reveal in VS Code | Open it in VS Code at the right place (also in the hierarchy's context menu, which goes to the node's line) |
A class can name a source file when it derives from UDreamTextUserWidget; the file is its class default
SourceFile. Doing the same from a script is in Scripting.
The text is the only truth
Once a class names a .dui, the file is the only truth about its hierarchy, and the designer is a graphical front
end for it. That buys one place to read, one to diff and one to review. It costs the designer the ability to do
everything — and it tells you so before the edit, rather than letting the edit live until the next compile and then
quietly vanish.
Values are written back. Change a property and the write-back lands on the line that holds the value —
whatever the node's type is written as, inside a @slot { … } block when there is one, and on a node with no id
by the id made for it. The designer never writes over a file that changed on disk (DUI7002). Moving a widget on
the canvas is a value edit too: it recomputes the anchors, and AnchorData.* is written back.
Structure belongs to the file. Creating, deleting, moving in the tree, renaming, duplicating and pasting
widgets, adding, removing or reordering behaviours, replacing a panel — on a class backed by a .dui each of these
is refused, with a message that names the file: structure lives in the text; edit the file to change it; the
designer edits values. The rotate and scale gizmos are withheld too, since the write-back carries AnchorData.*
and the language has no spelling for a relative rotation or scale.
Property rows that cannot be written back are disabled, with the reason:
| Reason | Example |
|---|---|
| The file writes it as a binding | Text <- GetTitle() — a literal would delete the binding |
| A loop made it | The N copies a for makes have no per-instance value to write |
| Outside the writable set | The write-back has no home for the property, so an edit would not survive a compile |
The value has no .dui spelling | In practice, object references: a font, a texture, a material. Pick a new font in the panel and the preview changes, the file does not, and the change is gone at the next compile |
The write-back also refuses a few cases out loud rather than writing them: a value that cannot be written as a literal
the language reads back (today, only non-finite floats) is DUI7003; a visibility an if decides, or a shorthand that
cannot take the change, is DUI7004; a value that comes from a + Component line of the node's style is DUI7005 —
the style is shared, and writing there would move every node that wears it. The codes are in
DUI7xxx.
A class whose hierarchy is built in the designer and names no .dui has none of these limits.
Events
The details panel's Events section lists the events the selected widget can raise. The + (Add Event Handler)
creates a custom event in the event graph with the right signature, and the route that names it — the same thing
as OnClick -> HandleConfirm in a .dui. When a handler exists, the same button opens it. Remove Event Route
takes the route away.
A route names a function on the user widget — the class the hierarchy compiles into — which is where UMG puts event
handling too. The compiler resolves every route into UDreamWidgetBlueprint::EventBindings, and
UDreamUserWidget::BindEventBindings attaches them at Initialize. It reaches both kinds of event this plugin has: the
BlueprintAssignable dynamic multicast delegates the controls declare, and the FDreamUIEventDelegate properties the
older Interaction/ behaviours declare.
FDreamUIEventDelegate's own per-instance event list is legacy and read-only. Bindings saved in it still fire and can
still be removed from the panel, but new ones are not authored there: such a binding calls a function on an arbitrary
object with a literal argument, which UMG has no equivalent of and .dui has no syntax for. Opening a panel that holds
one logs a warning naming it. Nothing is rewritten automatically — turning "call Foo on that behaviour with this
value" into "call a handler on the user widget" would change what the game does — so re-author them as routes when you
touch them.
The animation editor
The animation editor is built on Sequencer. A timeline block in a .dui compiles into a UDreamWidgetAnimation on
the class; because the file owns it, every compile rebuilds it, so the animation editor opens it read-only, says
why in the log, and refuses to rename it ("rename it in the .dui's timeline block").
To hand an animation to Sequencer, make its block external — below, Pulse belongs to the file and Celebrate to
the asset:
class /Game/UI/WBP_Results
Widget Root {
Text Title { Text = "Victory" }
}
timeline Pulse {
duration = 0.6
loop = PingPong
Title.RenderScale : 0.0 = (1, 1, 1), 0.3 = (1.25, 1.25, 1) ease InOutQuad, 0.6 = (1, 1, 1)
}
timeline Celebrate externalexternal builds nothing. It is a manifest entry: the animation lives in the asset, Sequencer edits it freely, and the
file still lists it — which is what makes "what animations does this class have" answerable by reading the file.
Material-parameter tracks, hand-shaped curves and anything else a timeline cannot express belong in external. See
Timelines.
Coming from UMG: the names are the same
The structure differs and the vocabulary deliberately does not — one table per UMG class in Resources/UMGParity, adopt / map / reject, the automation suite holding them against UMG's reflection both ways, and Docs/Reference printed from reflection.
The VS Code extension
Installing DreamGUI Language Support, what it does, where its completion data DUI/.dui-symbols.json comes from, the bridge to the running editor, and its commands and settings.