DreamFXLang
Language

The file model

The shape every DreamFXLang file shares — header, blocks, statements, comments, attributes — and an index of the eight L rules.

DreamFXLang has one file shape. The three extensions differ in what the top-level declaration is, not in the grammar.

<Kind>(Name = <string>[, Root = <string>])
{
    <block> …
}
NotationMeaningExample
<x>Placeholder — substitute a real value; the angle brackets are not typed.Name = <string>
[ x ]Optional — the whole group may be left out.[, Root = <string>]
{ a | b }Choice — take exactly one of the alternatives separated by |.{ Node( … ) | Comment( … ) }
Repetition — the preceding item may appear any number of times.<property-declaration> …
KindExtensionProduces
System.dfsa UNiagaraSystem
Emitter.dfenothing (copied into a .dfs by from)
Module / DynamicInput.dfma UNiagaraScript

A Kind that disagrees with the extension is DFX2021; one file holds exactly one top-level object, and anything after it is DFX2022. What Root accepts is in layout and naming.

Blocks, statements, attributes

Settings = {                       // a block: Name = { … }
    WarmupTime = 0.0;              // statements end in ;
}

Properties = {
    int SparkCount = 24 [ Group="Burst"; SortPriority=10 ];   // attributes hang off a declaration
}

// line comment
/* block comment */
  • a block is Name = { ... };
  • a statement ends in ;;
  • attributes are Key=Value pairs in brackets after a declaration, separated by ;;
  • comments are // and /* */.

#Region is only a comment

ParticleUpdate = {
    #Region "Forces"
    GravityForce(Gravity = (0, 0, -680));
    #EndRegion
}

#Region / #EndRegion exist for humans and editors to fold on. They do not reach the asset (that is L5): the external edit API has no stack-note function. An unclosed one warns (DFX2010); a stray #EndRegion is an error (DFX2005).

Names that are not identifiers

Niagara names come from a UI with no restrictions. Real content in this project has a user parameter called PillarPower(0~1) and a module input called Ring/DiscDistributionMode; neither is an identifier in any language. Back-quotes hold one:

Properties = {
    float `PillarPower(0~1)`;
}

ParticleSpawn = {
    SphereLocation(
        `Ring/DiscDistributionMode` = Direct,
        Alpha                       = `User.PillarPower(0~1)`,
    );
}

A back-quoted name is one token, dots included — `User.PillarPower(0~1)`, not User.`PillarPower(0~1)` . Only quote what needs it: `Speed` is legal but reads worse than Speed, and the decompiler applies exactly that rule. A name containing a back-quote has no written form at all — rename the parameter. An unterminated one is DFX1005.

The eight L* rules

The language's skeleton is eight rules, and the docs refer to them by name:

Rule
L1A stack is an ordered statement block. Six of them: SystemSpawn, SystemUpdate, EmitterSpawn, EmitterUpdate, ParticleSpawn, ParticleUpdate. Writing order is module order.
L2Two statement forms: a module call, and an assignment. Consecutive assignments fold into one Set Parameters module; a module call breaks the run. A new attribute is declared by its first write.
L3Four value modes: literal, linked, dynamic input, HLSL.
L4Module names resolve through Settings.ModulePaths; write a longer path only when a short name is ambiguous.
L5#Region is a comment. It does not reach the asset.
L6Inline expressions lower to one HLSL expression, and only whitelisted functions are allowed.
L7Numeric conversion widens, never narrows. int -> float is implicit; float -> int needs int(...).
L8Renderer properties are schema-driven generic assignment; every renderer type is supported without per-type syntax.

L2, L3, L6 and L7 are unpacked in values and rules, L1 in .dfs, and L8 in the renderer section of .dfs.

A page per file kind

What is deliberately not here

  • Emitter inheritance. from is copy, not inherit. Editing a .dfe does not reach back into systems that already copied it until they are rebuilt.
  • MaterialParam. Reserved syntax, not implemented (DFX5093).
  • Anything that would need a general expression compiler. See L6.

On this page