SystemGraph API
This section of the developer guide will introduce you to the API used when designing nodes for a system.
NodeRuntime API
NodeRuntime is an interface that a SystemGraph node will implement to enable interoperability with the SystemGraph mechanics, views and scheduler.
[NodeCategory("3D Printer", "Controller", NodeTick.Synchronous)]
public class UM2Controller : NodeRuntime
{
[Field("LCD Display", PortDirection.Left, FieldExtra.Read)]
[SerializeField]
private PortType<GameObject> lcdDisplayObject = new PortType<GameObject>();
[Field("Button Press", PortDirection.Left, FieldExtra.Read | FieldExtra.ChangeEvent)]
[SerializeField]
private PortType<bool> buttonPressed = new PortType<bool>();
[Field("Button Rotate", PortDirection.Left, FieldExtra.Read | FieldExtra.ChangeEvent)]
[SerializeField]
private PortType<float> buttonRotateAngle = new PortType<float>();
// ...
}
Scheduler
Scheduling of signals and life cycle events is managed by the scheduler. Configuration of the scheduler is executed from the SystemGraph editor environment.
Life cycle callbacks
Start Start event follows the unity GameObject lifecycle start event
Enable Enable event follows the unity GameObject lifecycle enable event
Disable Disable event follows the unity GameObject lifecycle disable event
OnTick The scheduler provided tick event according to the waveform frequency set in the SystemGraph Editor
Update Update event follows the unity GameObject lifecycle update event, when the node is configured to bind to unity lifecycle update callback
FixedUpdate FixedUpdate event follows the unity GameObject lifecycle FixedUpdate event, when the node is configured to bind to unity lifecycle FixedUpdate callback
IPortType
Port type is the container of information that is consumed by the connections between nodes. The Field attribute is used in conjunction with the port type to specify data access and data configuration.
SystemGraph provides a list of common port types to use and the user can also define his own custom port types through the IPortType interface.
The IPortType interface provides facilities to access data from a field of a NodeRuntime class and to register callbacks for ChangeEvents.
Port Batching
The IPortType interface provides a batching mechanism that stops propagation of information on a port, preventing change events from occurring until the batch context ends. The receiver node can register batch handlers that get signaled according to the current port batching state.
You can use port batching to improve performance when multiple ports of an asynchronous node change during the same cycle. Batching prevents the receiving node from processing data until the end of the batch is signaled.
Nodes can register handlers that intercept the state of batches. They can decide to accept the batching contract, or consume information anyway. A propagate function exists to signal a change event handler on the consumer port. Use the WriteRaw
property to bypass propagation events. This provides a way to optimize data propagation when the propagating node isn't ready to signal the change event to the consumer port.
Attributes
NodeCategory
NodeCategory
defines the behavior of the node.
[NodeCategory("Photosensors", "PhotosensorArray", NodeTick.Asynchronous)]
public class PhotosensorArray : NodeRuntime {...}
Category(string): Defines the name of the category in which to add this node
Name(string): Defines the name of the node that will be displayed in the graph
Mode(NodeMode bitmask): A combination of usage mode(s) of this node
- NodeMode.Standard: Display this node in the Create Node context menu
- NodeMode.Property: Display this node in the properties blackboard Add context menu
NodeTick(NodeTick): Define if this node receives OnTick event from the scheduler or not
- NodeTick.Synchronous: The node OnTick event is defined by the scheduler configuration
- NodeTick.Asynchronous: The node does not receive OnTick event
LifeCycle(LifeCycle): Add bindings to the lifecycle of the parent gameobject
- LifeCycle.Update: The node registers to the Update gameobject event
- LifeCycle.FixedUpdate: The node registers to the FixedUpdate gameobject event
DeferredAttribute(Type): Defer all attributes for this node from another node type
FrequencyHint(float): The default frequency set for synchronous node, in the scheduler
Field
Field
defines the behavior of a member port.
[Field("WaveLength", PortDirection.Left, FieldExtra.Read), SerializeField]
public PortTypeUint waveLength = new PortTypeUint(905);
DisplayName(string): Defines the name of the port that is displayed in the graph
Direction(PortDirection): Defines the direction position on the node for this port
- PortDirection.Undefined: Port Direction will be automatically assigned
- PortDirection.Left: Show the port on the left of the node
- PortDirection.Right: Show the port on the right of the node
Extra(FieldExtra): Defines customizations of the port
- FieldExtra.Undefined: No field extra configured
- FieldExtra.Clock: This field act as a clock source and can connect to anything to generate a change event
- FieldExtra.Read: This field reads data from another port
- FieldExtra.Write: This field writes data to another port
- FieldExtra.ChangeEvent: This field receives a change event when a value is written on the port. The developer can register a callback on change in the Enable callback of NodeRuntime.
- FieldExtra.Constant: This field value is a constant
ChangeEvent
The port ChangeEvent is the mechanism used by asynchronous nodes to react to changes to the input ports. You can register a callback in the Enable event:
[NodeCategory("Photosensors", "PhotosensorArray", NodeTick.Asynchronous)]
public class PhotosensorArray : NodeRuntime
{
[Tooltip("A signal indicating when to acquire the next image.")]
[Field("Trigger", PortDirection.Left, FieldExtra.Read | FieldExtra.ChangeEvent)]
[SerializeField]
protected PortType<CameraTrigger> trigger = new();
public override void Enable(Scheduler.ClockState clockState)
{
trigger.ChangeEvent += OnTrigger;
}
public override void Disable()
{
trigger.ChangeEvent -= OnTrigger;
}
private void OnTrigger()
{
// ...
}
}
Ports declared with FieldExtra.ChangeEvent
are displayed differently in the SystemGraph Editor: