Advanced Usage

This page contains the following topics:

Connection Types

To create a custom connection type for your nodes you need to write a simple interface class that defines the the request method of this connection. For example the IColorConnection interface can return a color and expects an request parameter to compute it. All nodes implementing that interface are able to return colors.

public interface IColorConnection
{
	Color GetColor(OutputSocket socket, Request request);
}

The OutputSocket parameter tells the implementing node which output socket is requested. This is useful if your node contains multiple output sockets of the same connection type.

In GDI every connection type has its own edge color for a better overview in the editor. The information about the color is obtained in the Node.cs class. To register a color for your custom connection find the static method GetEdgeColor in this class.

public static Color GetEdgeColor(Type connectionType)
{
	// ...
	if (connectionType == typeof(IColorConnection)) return AbstractColorNode.EdgeColor;
	// ...
}

The method maps a connection type to its color and returns it. In the case of the IColorConnection a static member of AbstractColorNode is used for the color. You could also directly return a color here or write an abstract class for your custom connection that contains the color.

Abstract Node Classes

You can write an abstract class for custom connection types as well. This classes are just helper classes that are optional. They usually have a static helper function for the connection type and can contain the edge color. Take a look at the existing abstract node classes if you like but you do not have to use them.

Request Parameter

Every connection interface should contain the request parameter in its method signature. Based on this parameter the node computes its return value.

public struct Request
{
	public float X;
	public float Y;
	public float Z;
	public float Seed;
	public float SizeX;
	public float SizeY;
	public float SizeZ;
}

Keep in mind that a connection type can have its own interpretation of the request parameter but should be compatible with other nodes.

For example: nodes that are implementing the IColorConnection interface usually bypassing the parameter and do not use it. One exception is the GradientNode. It uses the Y field of the request parameter to return the gradient color at this position.

Nodes that are returning numbers and implementing the INumberConnection interface often use the parameter. For example: the NoiseNode can return float values in 2 dimensions. For that reason the X and Z parameter is used. A node that creates a map of noise values like the DisplayMapNode simply requests a connected noise node for every position of the map. If also requests a connected gradient color node for every received number as the Y parameter.

Why do number nodes not return an array of numbers using SizeX and SizeZ? This is to avoid creating array instances for each node. We also can not create the array in one root node and just return the reference because of thread safety.

If you want to create custom connection types that are working well with the existing nodes you need to take a look how they are using the request parameter. You could also add more members to the request parameter but sometimes it is better to use one of the exiting ones in a clever, compatible way.

Custom Graph Evaluation

Writing a custom graph update and parse logic is an advanced topic. GDI implements a directed graph without cyclic dependencies.

A cyclic dependency is defined like this: A cyclic dependency should be detected if any OutputSocket of a Node has a indirect/direct path to any of its InputSockets. The path leads through OutputSockets only.

A cyclic dependency could lead to the situation that a node requests a value that is based on the same request. This would lead to a recursive request call and cause Unity to crash.

If you create a custom graph evaluation logic you need to be aware of issues like cyclic dependency. There are uses cases where you want to allow cycles anyway and evaluate the request values step by step. Take a look at the StandardGraphController class to find out more about the updating logic. Also take a look at the Graph class where you find the logic of parsing the graph, detecting cycles and allow/deny socket links.