DreamGUI
Concepts

Animation

The three ways to animate — tweens from the DreamTween module (RenderOffsetTo, RenderScaleTo, RenderAngleTo and RenderTranslationTo for widgets inside panels, EDreamTweenEase, DreamTween.MaxStepSeconds), widget animations (UDreamWidgetAnimation and Sequencer), and .dui timelines.

There are three ways to make things move in DreamGUI, each for its own kind of job:

WayGood forWhere
TweensMotion decided in code: entrances, hovers, a value changingThe DreamTween module, UDreamTweener
Widget animationsDesigned animations, edited in SequencerUDreamWidgetAnimation, embedded in the class
.dui timelinesWidget animations the text owns, rebuilt on every compileA timeline block in a .dui

Tweens

DreamTween is an independent, bottom-layer module. Every *To function returns a UDreamTweener you can chain on: SetEase, SetDelay, SetLoop (Once, Restart, Yoyo, Incremental; a count of -1 is infinite), SetTimeScale, SetAutoKill, and the callbacks OnStart, OnUpdate, OnCycleStart, OnCycleComplete, OnComplete and OnKill; to control it, Pause, Resume, Restart, Goto, ForceComplete and Kill.

Widgets, visuals and behaviours carry tweens of their own:

OnTweens
UDreamWidgetAnchoredPositionTo, SizeDeltaTo, WidthTo, HeightTo, RenderOpacityTo, LocalPositionTo, LocalScaleTo, LocalRotatorTo, WorldPositionTo, … and the render-transform tweens of the next section
UDreamVisualColorTo, AlphaTo
UDreamTextPaintLibraryPaintPhaseTo, PaintAngleTo, PlayShimmer (see Text)
UDreamTweenBPLibraryThe general FloatTo, Vector3To, ColorTo, MaterialScalarParameterTo, DelayCall, SpringFloat, …, and UMG_* tweens for UMG widgets

An easing is a name out of EDreamTweenEase, one word list for the whole plugin: Linear; In, Out and InOut with Quad, Cubic, Quart, Sine, Expo, Circ, Elastic, Back and Bounce; and CurveFloat, which follows a curve (SetCurveFloat). A widget tween defaults to OutCubic over 0.5 seconds.

A few rules that catch people:

  • Finished and killed tweens retire. The handle reads invalid, and a UPROPERTY holding it is nulled at the next garbage collection; Kill, ForceComplete and Goto do nothing on a retired tween, and Restart only warns. To play one again after it finishes, SetAutoKill(false) before it starts, or Restart it from its own OnComplete, which keeps it running.
  • Springs (SpringFloat) are held at rest by default; SetTarget wakes one.
  • A tween whose owner is gone is dropped without callbacks.

Pause and time dilation

Widget tweens follow the project settings: UI on the screen follows bScreenSpaceUIAffectByGamePause and bScreenSpaceUIAffectByTimeDilation (both off by default), everything else bWorldSpaceUIAffectByGamePause and bWorldSpaceUIAffectByTimeDilation (both on). Layout animations and the embedded UMG widget follow the same rule.

DreamTween.MaxStepSeconds (a console variable; 0, the default, is off) caps how far one frame moves the tweens: a frame longer than it — a screen loading its assets, the first draw of new text — moves the tweens the world ticks by the cap only. An entrance started just before such a hitch then plays on from where it was instead of appearing at its end. Manual ticks are never capped.

Widgets inside panels: animate the render transform

A panel writes its children's anchored position and size back on its next pass, so AnchoredPositionTo or LocalPositionTo on a widget a panel places only takes turns with the layout. What should move is what is drawn, not the layout:

TweenMoves
RenderTranslationTo(FVector)Translation in local space: X depth, Y right, Z up
RenderOffsetTo(FVector2D)The same move on the canvas plane (x right, y up), depth kept
RenderScaleTo(FVector)Scale about RenderTransformPivot
RenderAngleTo(float)The in-plane angle (SetRenderTransformAngle)

They move, scale and turn what is drawn and never the layout, so siblings do not make room. A widget whose render transform keeps changing is made a render layer by its canvas and moved on the GPU (see Rendering).

// Card sits in a VerticalBox: move what is drawn, not its slot
Card->SetRenderOpacity(0.0f);
Card->SetRenderTranslation(FVector(0.0, 0.0, -40.0));   // 40 below where layout put it
Card->RenderOpacityTo(1.0f, 0.25f);
Card->RenderOffsetTo(FVector2D::ZeroVector, 0.35f, 0.0f, EDreamTweenEase::OutCubic)
    ->OnComplete([]() { /* landed */ });

// An icon that keeps breathing
Icon->RenderScaleTo(FVector(1.15, 1.15, 1.0), 0.6f, 0.0f, EDreamTweenEase::InOutSine)
    ->SetLoop(EDreamTweenLoop::Yoyo, -1);

The same goes for components written in .dui: inside a panel, animate an instance through its render transform.

Widget animations

A UDreamWidgetAnimation is a UMovieSceneSequence embedded in the class, held in the root's animation component (UDreamWidgetAnimationComponent), with a class member variable like any other animation, and edited in Sequencer. It plays through UDreamUserWidget's entry points, which carry UMG's names: PlayAnimation, PlayAnimationByName, PlayAnimationForward, PlayAnimationReverse, PlayAnimationTimeRange, QueuePlayAnimation, PauseAnimation, GetAnimationByName, BindToAnimationStarted / BindToAnimationFinished, FlushAnimations. Playing returns an FDreamUIAnimationHandle, safe to keep: once the instance ends it stops being valid (UDreamUIAnimationLibrary::IsAnimationHandleValid).

  • What a track can drive: a property marked Interp. On a widget that is RenderTranslation, RenderRotation, RenderScale, RelativeLocation, RelativeRotationEuler (Sequencer has no property track for a quaternion, so rotation is animated through this Euler mirror), RelativeScale, PerspectiveFieldOfView and PerspectiveOrigin; on a visual, Color; on a text, its paint phases and PaintAngleOffset. The anchor block is a struct, and a struct has no property track, so a widget has animatable mirrors of it, shown on the track as Width, Height, Anchor Left and so on (AnimatableWidth, AnimatableHeight, AnimatableAnchorLeft, …).
  • Event tracks: keys on a DreamUI Event track are broadcast through OnAnimationEvent as playback crosses them.
  • C++ bindings: meta = (BindDreamWidgetAnim) says the class's code plays an animation of that name, so a hierarchy without one is a compile error; BindDreamWidgetAnimOptional makes the same claim without the error.
  • The player: an animation made only of plain property tracks is evaluated straight from its channels by DreamGUI's own player rather than through Sequencer's entity system (DreamUI.Animation.DirectEvaluation, DreamUI.Animation.LitePlayer, both on by default).

An ADreamWorldWidgetActor placed in a level can also be possessed by a Level Sequence directly, and WidgetOpacity, WidgetOffset and bWidgetVisible on its component are keyable (see World-space UI).

.dui timelines

A timeline block in a .dui is a widget animation the file owns. One line per track: a path of node ids, the property it drives, and the keys (time = value, each with an optional ease and an easing name). @time -> Name is a key on the event track.

timeline Pulse {
    duration = 0.6
    loop     = PingPong

    Icon.RenderScale            : 0.0 = (1, 1, 1), 0.3 = (1.25, 1.25, 1) ease InOutQuad, 0.6 = (1, 1, 1)
    Row/Title.RenderTranslation : 0.0 = (-40, 0, 0), 0.2 = (0, 0, 0) ease OutCubic
    @0.3 -> Landed
}

timeline Celebrate external

Widget Root {
    Image Icon { }
    Widget Row {
        Text Title { Text = "Ready" }
    }
}

The block compiles into a UDreamWidgetAnimation in the root's animation component, gets its member variable like any other animation, and plays through the same entry points. Because the file owns it, every compile rebuilds it and the animation editor opens it read-only — edit the .dui, or write timeline Name external to hand the animation to Sequencer for good. What a track may drive is exactly what the animation editor offers, and an easing is a name out of EDreamTweenEase, never a tangent. The full rules are on .dui timelines.

On this page