Diagram Structure

Glossary

Diagram card

Diagram card is a card that describes a diagram. It should be marked with [diagram enabled] attribute. It should contain at least one collection of blocks, an optional collection of links, and an arbitrary amount of fields that are not related to diagram representation.

Block record

Block record is a record (also called a ptototype) that represents a single shape in the diagram and toolbox. Block records should contain two mandatory fields: ref and layout, usually defined in the block variant ancestor. Block records should also have diagram archetype attribute defined. Instances (values) of block records are stored in collections in the diagram card.

Block archetype

Block archetype is a prdefined block shape supported by Hercules. There’s a limited amount of supported archetypes. Archetype is defined with diagram archetype attribute. Different block records (prototypes) can have the same or different archetypes.

Block connector

Connector is a slot on the block shape that can be connected with another connector of another block. Connectors are defined on block records (or block record fields) with a diagram connector attribute. Connectors have names that are unique within the block.

Anchor

Connector anchor is the unique identifier of block instance connector, which consists of block ref and connector name.

Link is a directed connection between two block connectors of different blocks. There’re anchor links and asset links, that can be mixed together in the same diagram. But asset connectors cannot be linked to anchor connectors and vice versa.

Anchor links are stored in the links collection in the diagram card. Anchor links are stored as pairs of connector anchors - from and to. Anchor links allow to create arbitrary oriented graphs, when each block can have multiple inputs and outputs.

Block record can have asset fields. Asset fields store references to target blocks, which are called asset blocks. Target connector name is not stored (which means that an asset block can have only one asset connector - but still an arbitrary amount of anchor connectors and/or asset fields). Asset fields can be optional or required, they can also store multiple values (if they are lists).

Connector categories

Connector can have a string category. If connector has a category, it can be linked only with another block connector of the same category. This shapes a simple type system.

Diagram Cards

In order for card (see Cards and Schema Root) to be displayed and edited as a diagram, it should be marked with diagram enabled attribute:

[diagram enabled]
record Card.CardDiagram // provide a meaningful type name instead
{
    ...
}

This card now represents the diagram, but toolbox is empty - we have not defined any blocks yet.

Diagram Blocks

Blocks are defined as variant records. Each descendant record defines a single diagram shape (a toolbox entry).

Block records should contain two mandatory fields: ref and layout, usually defined in the block variant ancestor.

// type name may be altered, but keep content as is
record Layout
{
    double x = 0;
    double y = 0;
}

// this alias is not required and serves self-documentation purpose. It can be renamed or omitted
define Ref atom;

enum BlockType
{
    example;
    ...
}

// provide a meaningful type name instead
variant Block
{
    Ref ref;           // Contains an auto-generated unique block id. Do NOT change the field name
    Layout layout;     // Contains block location. Do NOT change the field name.
    tag BlockType type;
}

[diagram archetype="box"]   // make it the diagram block and define the basic look
record Block.BlockExample[example]
{
    ...
}

The example above defines an example block record. Other variant descendants can be added to add more block types.

Note

Layout field is required for block location persistence, but it can also be useful to order blocks. For example, AI behavior trees are supposed to be read and processed left to right, application can use layout.x to find the proper order.

Now when blocks are defined, they should be stored in the diagram card:

[diagram enabled]
record Card.CardDiagram[diagram]
{
    list<Block> blocks = []; // provide a meaningful field name instead
    ...
}

Hercules will automatically detect all list fields containing diagram blocks. Most often there is one field, but there can be more, if several block variants are defined.

Now we’ve got a diagram with shapes, but they still cannot be linked together. Block connectors should be defined.