Relations - RealityStop/Bolt.Addons.Community GitHub Wiki
You may notice by now that certain units may show up, dim, orange, or red. These warnings and errors actual have code you utilize in a units Definition to help express when ports may be required in some sort of fashion.
This will be a much shorter, and easier tutorial. There is only 4 methods to be concerned about, that will get your Units providing proper errors and warnings for the user, so less mistakes exist during runtime.
Input and Events, these are your typical control roots. It is not a limit though. When you have a unit that is in charge of starting flow in a graph, this is what we call a Control Root. If your unit does not implement it, and a control root unit is not connected either directly, or through units that are connected to this unit, it will appear as dimmed, or partially transparent. To solve this, we use isControlRoot
.
You have two options. Override the property itself (both its getter and or setter), or set it with or without some logic in Definition.
public override bool isControlRoot => true;
protected override void Definition()
{
isControlRoot = true;
}
Requirement, says two things:
-
When you enter a Control Input port, you expect to get the Value Input port.
-
When you get a Value Output port, you expect the use a Value Input port.
For instance, with our Type Writer, we require both text and the delay to be assigned when we enter the start port. I'm going to take away the default values, else a value will always exist, just so you can see what happens.
If you would like to actually see what the relationships look like, you can turn on relation in the graph toolbar.
This would be done like this:
protected override void Definition()
{
start = ControlInputCoroutine("start", WriteText);
text = ValueInput<string>("text");
delay = ValueInput<string>("delay");
current = ValueOutput<string>("current", (flow) => { return storedText; });
typed = ControlOutput("typed");
complete = ControlOutput("complete");
exit = ControlOutput("exit");
Requirement(text, start);
Requirement(delay, start);
}
Succession, deals with the success of flow entry to output. It says, that the specific output port of a unit, might require you to enter an input port for the output to be invoked. There is no visual errors here, as it is only done on a possible scenario. You can see how its layed out by looking at the relations.
We know that all output Control ports cannot happen until the start port is entered. This will be our succession. Take a look:
protected override void Definition()
{
start = ControlInputCoroutine("start", WriteText);
text = ValueInput<string>("text");
delay = ValueInput<string>("delay");
current = ValueOutput<string>("current", (flow) => { return storedText; });
typed = ControlOutput("typed");
complete = ControlOutput("complete");
exit = ControlOutput("exit");
Requirement(text, start);
Requirement(delay, start);
Succession(start, exit);
Succession(start, typed);
Succession(start, complete);
}
Assignment is the last type of error handling for our units. This states one simple thing. Entering a ControlInput port may cause the output port to be assigned a value. In our case, when we enter, we immediately start assigning, but it is not in charge of assigning the variable itself. The coroutine does this. Just for example purposes, here is what that looks like:
Assignment(start, current);