Skip to main content

Execution Graphs

Graphs are a way for you to orchestrate things in your UI. The primary use case is for sequencing animations but there are plenty of use cases for this if you think outside the box a bit.

If you've used Behavior Trees, this will be quite familiar to you. The basic idea is that you execute a list of actions either sequentially or in parallel.

Here is an example. We have a box that we want to animate to the center of the screen. Wait for half a second, then rotate 180 degress while changing color.

Action<ElementHandle> graphBuilder = (root) => {
// we run a sequence of steps that execute one after the other
sequence(() => { // this isn't actually needed since the default graph root is already a sequence,but its here for illustration purposes

// run the first animation phase,use a parallel() because both animations should run at the same time
parallel(() => {
root.AnimateAlignmentOffsetX(Spring.Default.AnimateTo(new AlignmentOffset(0.5, AlignmentOffsetUnit.ScreenWidth));
root.AnimateAlignmentOffsetY(Spring.Default.AnimateTo(new AlignmentOffset(0.5, AlignmentOffsetUnit.ScreenHeight));

log("finished animating phase 0");

// when done animating, wait half a second

log("finished waiting 500 milliseconds");

// now animate rotation and background color at the same time
parallel(() => {
root.AnimateRenderTransform(Tween.LinearTo(new RenderTransform().Rotate(180));

log("finished animating phase 1");



GraphInstance graph = Graph.CreateGraph(someElement, graphBuilder);
graph.Execute(); // call this to tick the graph every frame

There are lots of baked in graph node types. They all live on the static class Graph.

It is recommended to use using static EvolveUI.ExecutionGraph.Graph; statement so you don't need to write in front of all your commands.graph

Sequence sequence(Action a)

Runs a set of steps sequentially. Each step will run until it completes, then the next step will run

Parallel parallel(Action a)

Runs a set of steps in parallel. This node completes when all of its children are finished

Log log(string message)

Logs the message and completes immediately

Log log(Func<string> fn)

Logs the result of the function and completes immediately

Pause pause(int milliseconds)

Pauses for the set number of milliseconds and completes when the duration has elapsed

AwaitEvent awaitEvent(string eventName)

Waits until the graph receives an event with the given eventName

EmitEvent emitEvent(string eventName)

Emits an event with eventName on the graph and completes immediately

WaitFrames waitFrames(int frameCount)

Waits frameCount frames and then completes

Custom Graph nodes

you can define your own graph actions by extending GraphNode. You just need to set IsCompleted at the right time and implement your Update override

Other Graph Nodes

the ElementHandle type provides wrappers around other node types like SetAttribute and Animate..