Key concepts

Three ideas carry the whole app: what flows on the wires, how nodes connect, and how one value resolves differently for every element.

Everything else in DNA is a variation on these three.

1. Collections

Almost everything that travels between nodes is a collection: a spreadsheet of things. Each row is one item, and each column is an attribute those items carry.

@P (position)@Cd (colour)@pscale (size)
0, 0, 0red1.0
1, 0, 0green0.5

Points, mesh vertices, shape outlines and plain rows of numbers all share this row-and-column shape. Every node adds rows, removes rows, or edits a column. Open the spreadsheet view on any node to see what is flowing through it.

Attribute names take an @ prefix when you reference them. @P is position, @Cd is colour, @id is each row's unique number.

Read more in Collections.

2. Connections

Drag a wire from one node's output into another node's input. The downstream node reads the incoming collection and passes a new one out.

Because every collection is the same underlying table, steps mix freely: scatter points on a shape, colour them from a table, then turn them into curves. Mismatched inputs convert automatically where a conversion exists.

When a node misbehaves, check the kind of its input, whether points, geometry, curves or a table. Hover a socket to read the kind on the wire, or open the spreadsheet.

See Creating & wiring nodes.

3. Context

A node does not hold a single value. Where it feeds many elements (many points, many copies, many loop passes), a value can resolve differently for each one.

Scatter 200 points with a Points node, add an The Expression language node, and write one rule:

float t = float(@ptnum) / float(@numpt - 1);
@Cd = {t, t, t, 1.0};

Each point reads its own ordinal, 0 through 199, divides by the count, and gets a brightness from 0 to 1. That is a smooth ramp across 200 points from two lines, with no loop written. You describe what happens to one element, and it is applied to every row.

@ptnum and @numpt are the ordinal and the count. They are worth learning first because they come from the loop rather than from a column, so they are available on any collection whatever attributes it carries.

Copies and loops work the same way. Iterator writes an @index column onto every copy, and For Start gives each pass its number on an output pin called $index, which you wire wherever it is needed. You author the relationship once, and every element, copy or pass fills in its own number.

A value varies per element only if it is a per-element attribute. A plain number typed into a parameter is one value shared by everything. To get variety, read an attribute (@ptnum, @id, @index) or feed a list instead of a single value.

Read more in Context: per-element values.

See also