# NixieFX Editor Manual

> Manual · Updated August 2026 · https://nixiefx.com/editor-manual/

How to use the NixieFX editor, end to end: opening projects and the
playground, the interface, the assets browser, every emitter module with
per-field reference tables, the curve and gradient editors, the timeline, the
PixiJS and Three.js preview backends, the node-based material editor, and
exporting effects your game can load.

This is the usage manual for the free browser-based editor at
https://nixiefx.com/editor/. For a capability overview of the whole system —
runtime integration, the export bundle format, agent skills — see
https://nixiefx.com/vfx-runtime-docs/. Effects are plain JSON files in a
folder on your computer; the editor never uploads anything. (The HTML version
of this page includes annotated screenshots of the full interface, the
effects library, the inspector, the timeline, the curve editor, the assets
browser, and the material editor.)

## Getting started

### Browser requirements

The editor runs at https://nixiefx.com/editor/ with no install and no
account. It reads and writes real folders on your computer through the
browser's File System Access API, which today ships in Chromium-based
browsers: **Chrome, Edge, Arc, Brave, or Opera**. In Safari or Firefox the
editor shows a full-screen notice instead of the launcher.

Nothing is uploaded. Projects are ordinary folders; the browser asks for
read/write permission per folder.

### The launcher

| Card | What it does |
| --- | --- |
| New Project | Opens the OS folder picker ("Pick a folder for a fresh effects workspace"). The editor writes a `vfx-editor.prj` file and a starter effect into the folder you choose. If the folder already contains a project, it simply opens it. |
| Open Folder | Opens the OS folder picker for an existing project. If the picked folder has no `vfx-editor.prj`, the editor asks: "<folder>" does not contain a VFX project. Create one in this folder? |
| Try the Playground | A ready-made sandbox project in a folder you pick — see below. Web build only. |
| Recent Projects | Up to 30 recently opened projects (most recent first) with a search box. Recents are stored in browser storage; the project files themselves stay on disk. |

### The playground

The playground is a **real project folder on disk**, not a browser sandbox,
so everything you author there is saved as normal files a game can load. The
first click walks you through setup:

1. A dialog explains the plan ("Set up your playground") and asks you to
   **pick an empty folder**. The playground project is copied into it, and
   the browser asks permission to access the folder.
2. If the folder you pick is not empty, the editor refuses — "The playground
   needs an empty folder so it can never overwrite anything of yours." — and
   offers to pick another.
3. If the folder already contains a VFX project, the editor offers to adopt
   it as your playground instead ("Project found — use it as your
   playground?").

After setup the playground folder is remembered. On later visits the same
card reopens it directly. Two recovery flows are built in:

- **Permission expired** — browsers periodically drop folder permissions.
  The editor shows "Folder access needed" and re-asks until you grant access
  or cancel.
- **Folder deleted or emptied** — if the remembered folder no longer
  contains a project, setup starts over from step 1.

If you used an older NixieFX build whose playground lived purely in browser
storage, its contents are copied into the disk folder you pick, so nothing
you authored is lost.

## Interface tour

### Top bar

| Control | What it does |
| --- | --- |
| Project switcher | A dropdown of every known project, with the active project's path shown next to it. The × button closes the active project and returns to the launcher, confirming first if there are unsaved changes. |
| Assets | Switches the bottom workspace to the Assets tab. |
| Settings | Opens the Project Settings dialog. |
| Create | With a project open, creates a **new effect** in the project. The new effect is seeded from the Starter Cone template, named "New Particle Effect", and the effects library opens with the name ready to rename. |
| Open | Opens another project folder (OS folder picker). |
| Buy us coffee | Opens the optional donation dialog. |

### Tool tabs: VFX and Materials

Two tool tabs switch the whole workspace: **VFX** (the particle editor) and
**Materials** (the shader graph editor). A dot appears on the Materials tab
while the open material has unsaved changes. Switching into Materials while
the current effect is dirty prompts to discard; switching back never prompts,
because material work is continuously auto-preserved in a per-project scratch
slot. The chosen tab is remembered between sessions.

### Viewport toolbar

| Control | What it does |
| --- | --- |
| Effects library | The effect-name button opens the effects library popover: a **+ New effect** button, a "Search effects…" filter, and one row per effect JSON in the project with inline **Rename** and **Delete** buttons. A dot on the button marks unsaved changes. |
| Save | Writes the current effect JSON to the project (Ctrl/Cmd+S). |
| Undo / Redo | Effect-level history (Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y). |
| Duplicate | Duplicates the current effect as "<name> Copy" and switches to it. |
| Status pill | The current editor status: `ready`, `edited`, `saved`, `exported`, and similar. |
| Pixi / Three toggle | Switches the preview renderer **and** the effect's target profile. Each button carries a support dot colored by that backend's live support status — supported, partial, or blocked — and the tooltip names the first blocker or warning. |
| Preview diagnostics | Toggles a stats overlay: fps, frame / update / sim / draw milliseconds, effect and particle counts, visible and emitted counts, sub-emitter spawns, render groups, upload bytes, and bloom activity. |
| Preview background | Popover with a background **Color** (default `#808080`), an optional **Image** texture on top of the color, and a **Lock image** toggle. On the Pixi backend the image can be dragged and resized on-canvas (Shift while resizing stretches freely); the Three backend does not draw the image. Preview-only. |
| Bloom | Preview-only HDR bloom (see Preview bloom below). |
| Floor grid | Toggles the 3D floor grid. Three backend only; disabled on Pixi. |
| Gizmos | A menu of per-gizmo visibility checkboxes with a visible/total count. |

### Viewport footer

- **particles** — active particle count over total capacity; **time** —
  preview time in seconds; **timing** — simulation milliseconds (hover for
  frame / update / draw ms and fps).
- **Play/Pause** and **Restart** — pause freezes the simulation; Restart
  replays from time 0. By default each restart picks a fresh random seed.
- **Reset view** — restores the default camera (double-clicking the viewport
  does the same).
- **Zoom slider** — camera zoom, 0.45×–2.5×.
- **ortho** — orthographic camera toggle (on by default).
- **auto-loop** — when a one-shot effect finishes (all emitters done, all
  particles gone), the preview automatically restarts. On by default.
- **lock seed** — keep the same random seed on every replay for bit-identical
  repetition. Off by default, so replays vary. Scrubbing and seeking never
  reseed regardless of this toggle.
- **FOV slider** — perspective field of view, 8–65 degrees; disabled while
  the camera is orthographic.

### Bottom workspace and inspector

The bottom panel has two tabs — **Assets** and **Timeline** — that share a
single toolbar row. Both stay mounted, so switching tabs never loses state.
Drag the handle above the panel to resize it (220–520 px; double-click
resets). The right-hand inspector hosts the emitter modules and the
Validation & Export panel; its width is also draggable (320–640 px).

## Projects and files

A NixieFX project is any folder containing a `vfx-editor.prj` settings file.
Effects are plain JSON files — the editable source of truth — and everything
the editor writes stays inside the project folder:

```
project/
  vfx-editor.prj        # project settings (paths below)
  *.json                # effect files (source of truth)
  materials/*.material  # shader graphs (JSON)
  ...textures, meshes   # any folder layout you like
  out/vfx/              # exported game bundle (read-only in the editor)
```

### Project Settings dialog

Top bar → **Settings**. Each row shows a Default/Custom pill; paths are
project-relative.

| Setting | Default | What it controls |
| --- | --- | --- |
| Effect Data | `.` | The folder scanned for effect `.json` files. It becomes the effects root in the Assets browser and the source root for export. |
| Export Output | `out/vfx` | Where Export Game VFX writes the game bundle. Also the read-only "Export Output" root in the Assets browser. |
| Allow External Output | off | When enabled, the output path may point outside the project root. |
| Asset Root | `.` | The base folder for texture and mesh references. Export copies referenced assets relative to it. |
| Materials Folder | `materials` | The sub-folder of the asset root where `.material` files live and are discovered. |
| Project File | — | Read-only: the location of `vfx-editor.prj`, which owns all of these paths. |

With the default settings (Effect Data and Asset Root both `.`) the Assets
browser shows two roots — **Project Files** and **Export Output**. When the
two paths differ it shows three: Particle Effects, Assets, and Export
Output. Export Output is always read-only.

## The Assets browser

The Assets tab is a three-pane file manager: a folder tree on the left, the
file view in the middle (with breadcrumbs and a status bar), and a details
inspector on the right.

### Toolbar

- **Create** menu — New Folder, New Particle Effect, New Material, and a
  "From Template" section with the effect templates *Impact Burst*,
  *Ambient Sparks*, and *Smoke Puff*. New effects and folders drop straight
  into inline rename; new effects open in the editor immediately.
- **Import** menu — Import Texture, Import Mesh, Import Effect JSON.
- File actions — Copy, Paste, Move, Duplicate, Rename, Delete, Reveal in
  Finder (desktop dev build only), Refresh.
- A recursive search box ("Search project...") that matches names and paths
  across the whole current root.
- **Sort** menu — Name, Type, Size, Date modified; Ascending / Descending.
  Folders always list first.
- **List view / Grid view** toggle. Both persist across sessions.

### Navigation and selection

- Back / Forward buttons walk a real history stack; "Up one folder" and
  clickable breadcrumbs move within the tree.
- Multi-select with Ctrl/Cmd+click (toggle), Shift+click (range), or a
  rubber-band marquee drag. Arrow keys, Home/End, PageUp/PageDown and
  type-ahead work in the file view.
- Double-click behavior by type: folders navigate; particle effects open in
  the VFX editor; materials open in the Material editor; textures and meshes
  just select.
- Texture files show live image thumbnails in both views.

### Drag and drop

- **Move** — drag entries onto a folder card, a tree row, or a breadcrumb.
  Invalid drops (same folder, folder into itself) are refused with a reason.
  The **Move...** action opens a destination-picker dialog for the same
  operation.
- **Import from the OS** — drop files anywhere on the browser: images become
  textures, `.glb`/`.gltf` become meshes, and `.json` imports as an effect
  (or a mesh when dropped in the assets root).
- Dragging a single texture or mesh onto a texture/mesh field in the
  inspector assigns it there.

### Context menu

Right-click an entry (or empty space) for: New Folder, New Particle Effect,
New Material, Import Texture / Mesh / Effect JSON, Open, **Export Game VFX**
(on effect files — exports just that effect), Rename, Copy, Paste, Move...,
Duplicate, Delete, Reveal in Finder (desktop only), and Refresh.

### Details pane and missing references

- **Textures** — preview, path, type, size, modified date, a reference
  count, and a "Referenced by" list of the effects and emitters using the
  texture ("Unused by saved effects" when none).
- **Effects** — file, **emitter count**, modified date, and a validation
  pill. The open effect shows its live validation summary ("Valid" or
  "N errors, N warnings") plus an `open` / `open (unsaved)` badge; other
  effects show "Open to validate".
- **Materials** — file, node count, modified date.
- The status bar shows the current location, item and selection counts, and
  — when any saved effect references a file that no longer resolves — a
  warning counter like "2 missing asset refs".

## Authoring particle effects

An **effect** is a set of **emitters**; each emitter is configured through a
fixed stack of **modules** in the right-hand inspector. Select an emitter by
clicking its track in the timeline; add one with the **+** button in the
timeline toolbar. The inspector starts with a locked **Effect** section
(effect Id and Name), then the emitter modules in two groups
("Runtime-bound emitter modules" and "Extended emitter modules"), and ends
with Validation & Export.

### Module conventions

- Every module is a collapsible section. Optional modules have an **enable
  checkbox** in the header; structural modules (Initialize Particle, Shape,
  Renderer, Emission) are always on. There is no "add module" picker — the
  stack is fixed. The one exception is Shader Custom Data, which hides
  behind a **+ Shader Custom Data (advanced)** button until enabled.
- Some modules have a **recipe menu** ("Apply a module recipe") with
  one-click presets; recipes may adjust related modules too.
- Number fields are Blender-style: **drag to scrub**, click to type, arrow
  keys nudge by one step, hold Shift while dragging for 0.1× fine control.
  Bounded values render as filled sliders; unbounded ones as steppers.
- Backend-specific behavior is called out in inline notes under the affected
  field.

### Value modes

Most scalar fields accept more than a constant. The chevron next to the
field ("Value mode") opens a menu:

| Mode | Behavior |
| --- | --- |
| Constant | One fixed value. |
| Random Between Two Constants | Two inputs (min, max); each particle samples a uniform random value between them. |
| Curve | A curve sampled over the chosen x-axis. Clicking the curve thumbnail opens the curve editor. |
| Random Between Two Curves | Two curves (A and B); each particle samples between them. |

The same menu always ends with a **Curve Range** row — two numbers setting
the curve editor's vertical range for this field.

### Main

The module checkbox here enables or disables the **whole emitter**.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Name | text | Emitter | Also editable inline on the timeline track. |
| Mode | Billboard · 2D shard mesh (Pixi) · Mesh particle (3D) | Billboard | "Mesh particle (3D)" is offered only while the effect targets the Three backend. |
| Start Delay | stepper, seconds | 0 | Min 0, step 0.05. Same value as the timeline clip position; read-only while the track is locked. |
| Duration | stepper, seconds | 1 | Min 0.05, step 0.05. Equals the clip length. |
| Looping | toggle | On | Looping emitters draw ghost repeats on the timeline. |
| Max Particles | stepper | 128 | 1–4096. Per-emitter capacity cap. |

### Emission

Always on (dims with the emitter). Recipes: Steady, Burst, Aura, Trail.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Rate over Time | scalar | 24 | Particles per second, 0–3000. |
| Rate over Distance | scalar | 0 | Particles per world unit moved, 0–1000. |
| Bursts | table | none | Columns: time (0–60 s), count (1–4096), cycles (1–256), interval (0–60 s), chance (0–1). "Add Burst" appends a row (count 16, cycles 1, interval 0.1, chance 1); up to 16 rows. |

### Initialize Particle

Always on. The single source of every particle's initial state.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Emitter Position | vector X/Y/Z | 0, 0, 0 | World-space spawn origin, ±100. Also draggable with the on-screen move gizmo. |
| Lifetime | scalar, seconds | 1 | Min 0.02 s. |
| Start Color Mode | Constant · Random Between Two · Gradient (by seed) · Random Between Gradients | Constant | The gradient modes sample gradients stored in the effect JSON; the inspector currently exposes swatch editing only for the first two modes. |
| Start Color / Start Color B | color swatch | #FFFFFF | B appears in "Random Between Two" mode. |
| Initial Alpha | slider | 1 | 0–1. |
| 3D Start Size / Start Size | toggle + scalar (or X/Y/Z) | off / 1 | Billboard emitters. Mesh emitters show **Start Scale** (X/Y/Z) instead. |
| 3D Start Rotation / Start Rotation | toggle + scalar (or X/Y/Z), degrees | off / 0 | Displayed in degrees (stored radians). Mesh emitters always show the three-axis row. |
| Start Velocity Mode | Shape Direction · Vector | Shape Direction | — |
| Start Speed | scalar, units/s | 0 | Shape Direction mode. |
| Min Velocity / Max Velocity | vector X/Y/Z, units/s | 0, 0, 0 | Vector mode: a per-axis random range. |

### Shape

Always on. Fields appear per shape.

| Field | Control | Default | Applies to |
| --- | --- | --- | --- |
| Shape | Point · Circle · Box · Cone · Sphere · Hemisphere · Mesh | Point | — |
| Simulation Space | World · Local | World | All shapes. World keeps live particles where they spawned when the emitter moves; Local keeps them attached to the emitter transform. |
| Angle | stepper, 0–90° | 25 | Cone. |
| Radius | scalar, world units | 0 | Circle, cone, sphere, hemisphere. |
| Radius Thickness | slider 0–1 | 1 | Same shapes. 0 = shell, 1 = full volume. |
| Arc | stepper, 0–360° | 360 | Circle, cone, sphere, hemisphere. |
| Arc Mode | Random · Loop · Ping Pong · Burst Spread | Random | Same shapes. |
| Spread | slider 0–1 | 0 | Same shapes. |
| Arc Speed | scalar, ±360 °/s | 0 | Only when Arc Mode is Loop or Ping Pong. |
| Box Size | vector X/Y/Z, 0–48 | 0, 0, 0 | Box. |
| Emit From | Base · Volume | Base | Cone. Volume adds a **Length** field (default 5). |
| Emission Mesh | mesh asset picker | none | Mesh shape. Paired with **Emit From**: Surface (area-weighted points across triangles) or Vertices. Spawn direction follows the surface normal. Three backend only; Pixi falls back to point emission. |
| Rotation / Scale | vectors | 0,0,0 / 1,1,1 | All shapes; orients and scales the shape itself. |
| Randomize Direction | slider 0–1 | 0 | All shapes. |
| Spherize Direction | slider 0–1 | 0 | All shapes. |
| Randomize Position | stepper, 0–24 units | 0 | All shapes. |

### Forces (Gravity & Drag)

Optional. Initial velocity is set in Initialize Particle; this module applies
gravity and drag over the particle's age.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Gravity Modifier | scalar (signed) | 0 | Multiplier on world gravity. |
| Drag | scalar | 0 | Velocity damping per second, min 0. |

### Velocity over Lifetime

Optional. Adds linear, orbital, and radial velocity over the particle's age —
computed analytically, so motion is deterministic and identical on both
backends.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Space | Local · World | Local | Local rotates/orbits around the emitter; World uses world axes and the spawn origin. |
| Linear | X/Y/Z scalar row, units/s | 0 | Each axis supports constant / random / curve. |
| Orbital | X/Y/Z scalar row, rad/s | 0 | Angular velocity around each axis. |
| Orbital Offset | X/Y/Z scalar row, units | 0 | Moves the orbit center. |
| Radial | scalar, units/s | 0 | Outward (or inward, negative) from the center. |
| Speed Modifier | scalar 0–4 | 1 | Multiplies the final velocity. |

### Color over Lifetime

Optional. Recipes: White, Fire, Smoke, Magic.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Color | gradient | white → white | Sampled over normalized age and multiplied onto the particle's start color. |
| Emissive Intensity | scalar, exposure stops | 0 | 0 is neutral, +1 doubles brightness, −1 halves it. The slider spans ±10 stops; typed values can go further (hard cap 50). Preserved linearly in export for the game's own HDR/bloom pipeline. |

### Size over Lifetime

Optional. Recipes: Constant, Shrink, Grow, Pop.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Billboard Separate Axes | toggle | off | Off: one **Billboard Size** value (0.001–24). On: separate **Billboard Size X / Y** curves. |
| Billboard Softness | slider 0–1 | 0.4 | Soft-edge falloff of the procedural billboard. |
| Mesh Separate Axes / Mesh Size | toggle + scalar (or X/Y/Z) | off / 0.28 | Size for mesh-mode particles, 0.001–24. |
| Mesh Thickness | stepper 0.02–4 | 0.5 | Extrusion depth of 2D shard meshes. |

### Rotation over Lifetime

Optional. Controls only over-life spin — Start Rotation (from Initialize
Particle) always sets the initial angle. Recipes: Still, Random, Spin,
Tumble.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Separate Axes | toggle | off | Splits spin into X/Y/Z. |
| Angular Velocity | scalar (or X/Y/Z row), °/s | 0 | Displayed in degrees per second (stored radians). |

### Renderer

Always on; starts collapsed. Recipes: Glow, Sprite, Smoke, Shards.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Surface | Texture \| Material radio | Texture, none | An emitter draws through a texture **or** a material, never both. Texture mode opens the texture picker; Material mode selects "Sprite Master (built-in)" or any project material and shows the MainTex override plus instance parameters. |
| Blend Mode | Alpha · Additive · Premultiplied Alpha | Alpha | Dimmed with "Driven by material." when a custom material is assigned — Masked and Opaque blending are material settings. |
| Shading | Unlit · Lit (Three 3D) | Unlit | Lit reacts to the Three preview scene lights; Pixi keeps unlit compositing and reports a warning. |
| Alignment | Screen · Current Velocity · Spawn Direction · Fixed Vector | Screen | Which local axis the billboard pins. Fixed Vector adds an **Alignment Vector** field (default 0, 1, 0). |
| Facing | Camera Plane · Camera Position · Off | Camera Plane | Whether the aligned billboard spins around its pinned axis to face the camera. |
| Opacity Source | Texture Alpha · Red · Green · Blue · Luminance · Inverse Luminance · Constant | Texture Alpha | Derives per-pixel alpha from a texture channel so RGB-only textures can alpha-blend. Non-default choices add an **Invert Opacity** toggle. |
| Mesh Asset | mesh picker + Flip Winding + Recompute Normals | none / off / off | Mesh particle (3D) mode only. |
| Mesh Template | Triangle shard · Quad shard · Shard | Triangle shard | 2D shard mesh mode only. |
| Billboard Pivot / Mesh Pivot | vector, ±2 | 0, 0 | Signed pivot offset as a fraction of size; negative values allowed. |
| Depth Test / Depth Write / Depth Ink | toggles | on / off / on | Three uses the real GPU depth buffer; Pixi approximates with deterministic 2.5D draw ordering and "depth ink". |
| Order in Layer | stepper, −1024…1024 | 0 | Sorts emitters within the effect; higher draws in front. |
| Sort Mode | By Distance (Far First) · By Distance (Near First) · Oldest In Front · Youngest In Front · None (Spawn Order) | By Distance (Far First) | Far First is the alpha-correct painter order. |

**The texture picker** — texture slots open a searchable grid of the
project's images with a **None** card ("No texture (procedural shape)") that
falls back to the built-in procedural billboard. You can import from the
picker (button or drag-and-drop); accepted formats are .png, .jpg, .jpeg,
.gif, .webp, .bmp, .svg and .avif. Mesh slots work the same way for .glb,
.gltf and mesh .json files.

### Limit Velocity over Lifetime

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Separate Axes | toggle | off | Off: one **Speed** cap. On: **Limit X / Y / Z**, each 0–120 units/s. |
| Space | Local · World | Local | — |
| Speed | scalar, 0–120 | curve at 16 | The clamp threshold over lifetime. |
| Dampen | slider 0–1 | 0.5 | How hard speeds above the limit are pulled down. |
| Drag | scalar, 0–12 | 0 | Extra damping applied by this module. |
| Multiply by Size | toggle | off | Scales drag with particle size. |

### Inherit Velocity

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Mode | Initial · Current | Initial | Inherit the emitter's velocity at spawn, or track it continuously. |
| Multiplier | scalar, −4…4 | 0 | Fraction of emitter velocity applied. |

### Lifetime by Emitter Speed

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Speed Range | Min / Max, 0–80 | 0 – 16 | Emitter speeds mapped onto the curve's 0–1 axis. |
| Lifetime Multiplier | scalar, 0–3 | 1 | Scales start lifetime by emitter speed. |

### Force over Lifetime

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Force | vector X/Y/Z, ±160 | 0, 0, 0 | Constant acceleration (units/s²). |
| Randomized | vector X/Y/Z, 0–160 | 0, 0, 0 | Per-particle ± random addition per axis. |
| Multiplier | scalar, −10…10 | 1 | Scales the whole force. |

### Color by Speed

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Speed Range | Min / Max, 0–80 | 0 – 16 | Particle speeds mapped onto the gradient. |
| Color | gradient | white → orange | — |
| Blend | slider 0–1 | 0 | Mix with the particle's lifetime color. |

### Size by Speed

| Field | Control | Default |
| --- | --- | --- |
| Speed Range | Min / Max, 0–80 | 0 – 16 |
| Size Multiplier | scalar, 0–4 | 1 |
| Blend | slider 0–1 | 1 |

### Rotation by Speed

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Speed Range | Min / Max, 0–80 | 0 – 16 | — |
| Angular Velocity | scalar, ±24 rad/s | 0 | This module uses rad/s, not degrees. |
| Blend | slider 0–1 | 1 | — |

### External Forces

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Wind | vector X/Y/Z, ±160 | 0, 0, 0 | Constant wind acceleration. |
| Gravity Multiplier | scalar, −4…4 | 1 | — |
| Drag | scalar, 0–12 | 0 | — |
| Vortex Strength | stepper, ±80 rad/s | 0 | Swirl around the emitter. |

### Noise

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Mode | Sine · Curl | Sine | Sine jitters each particle independently. Curl advects everything through one shared, divergence-free turbulence field — nearby particles swirl together. |
| Strength | scalar, 0–8 | 0 | — |
| Frequency | stepper, 0–32 | 1.5 | Cycles per world unit. |
| Speed | stepper, ±16 | 1 | Field animation speed. |
| Scroll | vector X/Y/Z, ±16 | 1, 0, 0 | Field scroll velocity. |
| Octaves | stepper, 1–6 | 2 | — |
| Damping | slider 0–1 | 0.5 | — |

### Plane Collision

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Mode | None · World plane | None | Analytic bounce against a horizontal world plane. |
| Plane Y | stepper, ±100 | 0 | Height of the plane. |
| Radius | stepper, 0–16 | 0 | Particle collision radius. |
| Bounce | slider 0–1 | 0.35 | Restitution; multiple decaying bounces supported. |
| Dampen | slider 0–1 | 0.45 | Tangential speed loss per bounce. |
| Kill Below | stepper, 0–200 | 20 | Kills particles that bounce slower than this. |

### Triggers

Named runtime events your game code can listen for. Event names are
free-form strings.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Birth Event | text | empty | Fired when a particle spawns. |
| Death Event | text | empty | Fired when a particle dies. |
| Normalized Time | slider 0–1 | 1 | A normalized-age crossing that also fires an event. |
| One Shot | toggle | on | Fire once per particle vs. on every crossing. |

### Sub Emitters

Three fixed slots — **Birth**, **Collision**, **Death** — each spawning
another effect file from this project:

| Per-slot field | Control | Default |
| --- | --- | --- |
| Effect | dropdown of project effects (or None) | None |
| Probability | slider 0–1 | 1 |
| Inherit Color | toggle | on |
| Inherit Size | toggle | on |

Sub-emitters currently run on the Pixi backend; enabling the module reports a
blocker on the Three backend.

### Texture Sheet Animation

Flipbook animation over a uniform sprite-sheet grid.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Tiles | X / Y, 1–16 each | 1 × 1 | Grid dimensions of the sheet. |
| Start Frame | stepper, 0–255 | 0 | — |
| End Frame | stepper | whole sheet | Clamped to tiles X × Y − 1. |
| Frame over Time | scalar curve, 0–255 | flat 0 | Frame index sampled over lifetime. |
| Cycles | stepper, 0–32 | 1 | Playthroughs per particle lifetime. |
| Random Start | toggle | off | Random start frame per particle. |

### Particle History Trails

Per-particle ribbons. Three renders a camera-facing world-space ribbon from
particle centers; Pixi renders a screen-space particle-history approximation.

| Field | Control | Default | Notes |
| --- | --- | --- | --- |
| Ratio | slider 0–1 | 1 | Fraction of particles that grow trails. |
| Lifetime | scalar, 0–8 s | 0.5 | How long each trail point lives. |
| Length (0 = lifetime) | scalar, 0–12 | 0 | Fixed length cap, or 0 to follow point lifetime. |
| Width | scalar, 0.01–4 | 1 | — |
| Width over Trail | curve | flat 1 | Sampled along the trail: 0 is the head/newest point, 1 the tail/oldest. |
| Min Vertex Distance | slider 0–1 | 0.02 | Minimum spacing between trail points. |
| World Space | toggle | on | Trail points stay behind in world space. |
| Inherit Color | toggle | on | Trail tint follows the particle color. |
| Texture | texture picker | procedural | A dedicated trail texture, or the default. |
| Texture Mode | Stretch · Tile | Stretch | — |

### Shader Custom Data

Four per-particle scalar channels (each supporting constant / random / curve,
range −1…1) plus a label. When the emitter is bound to a material with a
**DynamicParameter** node, the channels take that node's names and feed it
directly. Until then the channels are named Param1–Param4. Pixi delivers the
channels as one emitter-level representative value; Three evaluates random
and curve channels per particle.

## Curves and gradients

### The curve editor

Clicking any curve thumbnail opens **Particle System Curves** — a draggable
floating panel (Escape closes it; its position is remembered). The toolbar
shows the value axis with the field's unit, a **Multiplier** ("Multiplies the
graph output after the curve is evaluated"), and the **X** axis: **Particle
Lifetime** (normalized particle age, the default) or **Loop Age** (the
emitter's normalized loop time). In Random Between Two Curves mode, **Curve
A** / **Curve B** tabs switch the edited side; both curves stay visible with
the band between them filled.

- **Add a point** — double-click the canvas. **Remove** — select and press
  Delete/Backspace, or the Remove button. Curves keep at least 2 and at most
  8 points. The first and last points are locked to x = 0 and x = 1.
- **Select** — click a point; Shift+click toggles; drag on empty canvas
  draws a marquee. With two or more points selected, a transform box appears
  with eight scale handles — drag the body to move the group, drag a handle
  to scale it.
- **Tangents** — the primary point shows draggable in/out Bezier handles
  (dragging sets slope and weight together). The point row exposes numeric
  T, V, In, Out, Win, Wout fields and the tangent mode buttons **Auto**
  (shape-preserving), **Flat** (slope 0 — stops overshoot), **Linear**
  (through neighbouring keys), **Break** (independent sides) and **Unify**
  (one symmetric slope).
- **Value range** — double-click the top or bottom axis label to type a new
  bound (the top label adjusts the multiplier; the bottom sets the minimum),
  or use the Curve Range row in the value-mode menu.
- **Optimize** — simplifies the curve by removing redundant points at the
  chosen tolerance (Tol 0.001 / 0.005 / 0.01 / 0.025), preserving endpoints
  and sharp spikes.
- **Presets** — built-ins Hold, Rise, Warm Up, Snap In, Pulse, Fade, Soft
  Fade, Late Pop, S-Curve, and Blink, remapped into the field's current
  range. The **Saved** row saves and loads your own named presets per
  project; saving under an existing name overwrites it.

The drawn stroke is sampled by the same runtime curve evaluator the game
uses, so what you see is exactly what plays back.

### The gradient editor

Gradient swatches (Color over Lifetime, Color by Speed, material Gradient
Ramp nodes) open the **Gradient** floating panel:

- **Blend / Fixed** — smooth interpolation between stops, or hard stepping
  where each stop holds until the next.
- Two stop tracks around the gradient bar: **alpha stops on top, color stops
  below**. Double-click a track to add a stop; double-click a stop (or use
  the trash button) to remove it; drag to move. Up to 8 stops of each kind;
  the last one of a kind cannot be deleted.
- A selected color stop shows its **Color**, a **Location** percentage, a
  duplicate-stop button, and an embedded color picker. A selected alpha stop
  shows an alpha slider plus a 0–255 value and its Location.
- Presets: White Fade, Ember, Smoke, Magic, Poison, Ice.

### The color picker

Color swatches open a compact picker: a saturation/value square, a vertical
hue strip, a 6-digit **HEX** field, and **R / G / B** inputs (0–255). The
picker is RGB-only — alpha is edited through gradient alpha stops or the
Initial Alpha field, and HDR brightness through Emissive Intensity.

## The timeline

The Timeline tab shows one track per emitter. Clicking a track selects that
emitter in the inspector.

### Tracks and clips

- Per-track buttons: **Loop** (emitter looping), **Solo** (preview only this
  emitter — an editor-side preview state, not saved into the effect),
  **Lock** (protects the track from edits), and **Mute** (disables the
  emitter — saved into the effect JSON).
- **Drag the clip body** to change the emitter's start delay. **Drag the
  left edge** to move the start while pinning the end (changes delay and
  duration). **Drag the right edge** to change the duration. Dragging past
  the end of the timeline grows the effect duration. Minimum duration is
  0.05 s.
- Double-click a track or clip name to rename inline (Enter commits, Escape
  cancels). Reorder emitters with **Move up / Move down** in the context
  menu.
- **Groups** — effects whose JSON defines timeline groups show group rows
  with collapse, group-lock, and group-hide controls (hide toggles every
  member emitter). The editor does not currently create groups itself.
- Right-click a track for the full context menu: Rename, Copy, Paste,
  Duplicate, Enable/Disable loop, Lock/Unlock, Mute/Unmute, Solo/Unsolo,
  Move up/down, Delete. Right-clicking empty space offers **Paste at
  playhead**.

### Transport and tools

The tab strip hosts a single toolbar row: emitter tools (add emitter at
playhead, snap magnet, copy / paste / duplicate, loop, lock, mute, delete),
then the transport — jump to start, step back one frame, play/pause, step
forward one frame, jump to end, **Loop playback range**, and **Restart
effect** — followed by the playhead readout, a **Frames / Seconds** unit
toggle, an **FPS** field (1–240, presets 24, 25, 29.97, 30, 50, 60, 120 —
display-only: it changes labels and the snap grid, never playback speed),
and zoom controls with a **Fit** button.

- **Scrubbing** — drag the ruler or playhead. Seeks are deterministic:
  scrubbing backward re-simulates from time 0 with the same seed, so the
  state you land on is exactly what playback would have produced. Scrubbing
  never reseeds and never toggles play/pause.
- **Loop range** — with "Loop playback range" on, a bracket appears on the
  ruler; drag its ends or middle to set the range. Each loop wrap picks a
  fresh seed unless **lock seed** is on.
- **Snap** — the magnet toggles snapping to the frame grid (or the visible
  seconds grid in Seconds mode); off allows subframe drags.
- **Zoom** — the slider or Ctrl/Cmd+wheel over the lanes (0.1×–12×).

## Preview, camera and backends

### Pixi and Three backends

The preview renders through the same `nixie-fx` runtime games embed, with
two switchable backends. The **Pixi / Three** toggle in the viewport toolbar
also sets the effect's target profile, which is saved in the effect JSON:
Pixi ⇒ `pixi-ui-2d`, Three ⇒ `three-world-3d`. New effects and all bundled
templates default to `three-world-3d`. (A third profile, `portable`, means
"must satisfy both backends"; the editor previews portable effects through
Pixi.)

Each toggle button carries a **support dot** — supported, partial, or
blocked — computed live from the current effect, and the tooltip names the
first blocker or warning (for example, mesh particle assets are Three-only,
sub-emitters are currently Pixi-only, lit shading warns on Pixi). The same
per-backend reports are written into every export.

### Camera

| Input | Action |
| --- | --- |
| Left-drag | Pan |
| Middle-drag | Orbit |
| Wheel | Zoom (0.45×–2.5×) |
| Double-click | Reset view |

Bindings are identical on both backends, and the camera state is remembered
per project. The **navigation gizmo** in the viewport corner shows the
current orientation: click an axis ball (+X, −X, +Y, −Y, +Z, −Z) to snap to
that view (snapping forces orthographic on), click the center to toggle
perspective/orthographic, drag the disc to orbit, or wheel over it to zoom.
The camera starts orthographic; the **ortho** checkbox and the FOV slider
(8–65°, perspective only) live in the viewport footer.

### Gizmos

- **Shape outlines** (Circle / Box / Cone / Sphere / Hemisphere) —
  wireframes with draggable handles that edit the module values directly:
  radius, box width/height/depth, cone radius/length/angle. Visible by
  default.
- **Move origin** — a translate gizmo on the emitter origin with X/Y/Z
  arrows, plane handles, and a ground-plane center handle. It edits
  Initialize Particle → Emitter Position. Visible by default.
- **Particle pivots** and **Particle wireframes** — per-particle debug
  overlays (pivot crosses and quad outlines for the selected emitter).
  Hidden by default.

### Preview bloom

The **Bloom** button opens the preview bloom popover. Bloom is a **preview
aid only** — stored in browser storage per project and never saved into
effects or exports. Your game applies its own bloom; the editor's exists so
HDR emissive values can be judged visually.

| Control | Range | Default | Meaning |
| --- | --- | --- | --- |
| Bloom | on / off | on | Master toggle; the sub-label reports live source-particle, pass, and render-scale stats. |
| Threshold | 0–10 | 1 | Minimum HDR brightness that contributes to bloom. |
| Intensity | 0–4 | 4 | Strength of the final bloom add. |
| Exposure | −2…2 | 0 | Preview tonemap exposure in stops. |
| Scatter | 0–1 | 0.7 | How far bloom spreads through the pyramid. |
| High Quality Filtering | on / off | off | Smoother filtering at a higher render cost. |
| Downscale | Quarter · Half | Quarter | Bloom render resolution. |

## Materials and the shader graph

The **Materials** tool tab is a node-based shader graph editor in the spirit
of Unreal's material editor. A material is a graph that outputs
**baseColor**, **emissive**, **opacity**, and **opacityMask**; any output
left unwired shows a *(fixed)* tag and falls back to the built-in Sprite
Master fixed-function behavior. Materials are saved as `.material` JSON
files in the project's materials folder.

### Creating and saving materials

- **+ New Material** in the sidebar creates an in-memory draft; the Assets
  browser's Create menu and context menu create the file immediately and
  open it. Double-clicking a `.material` in the Assets browser opens it too.
- New materials seed with the Sprite Master parameter set — **MainTex**
  (texture), **Tint** (color), **Emissive** (float), and **Opacity** (float)
  — plus an Output node.
- **Save** lives in the graph toolbar (a name prompt appears for unsaved
  drafts). Work in progress is also auto-preserved per project. Note:
  Ctrl/Cmd+S saves only in the VFX view — in the Materials view use the
  Save button.

### Working the graph

- **Add nodes** — click a palette entry (drops at the view center), drag it
  onto the canvas, or right-click empty canvas for a searchable "Add node…"
  menu.
- **Connect** — drag from an output pin to an input pin. Inputs take one
  connection; outputs fan out. Texture pins only connect to texture pins;
  float and vector types inter-connect freely (floats broadcast). Invalid
  connections flash the reason.
- **Rewire / disconnect** — Alt+click a pin breaks its connections;
  Alt+click an edge deletes it; dragging from a wired input pin picks the
  wire up to re-drop elsewhere; hold Ctrl/Cmd to grab an existing edge end.
- **Edit** — Ctrl/Cmd+C / V / D copy, paste and duplicate selected nodes;
  Delete removes them (the Output node cannot be deleted); undo/redo with
  Ctrl/Cmd+Z / Ctrl/Cmd+Shift+Z. Pan with middle- or right-drag; left-drag
  box-selects.
- **Previews** — the right-hand Preview panel renders the material; select a
  node and press **Start Previewing Node** to inspect any intermediate
  output (with a pin selector for multi-output nodes). Selected nodes with
  animated inputs also draw a live inline preview, and Noise nodes always
  show their baked swatch. Right-clicking a Constant offers **Promote to
  Parameter**.

### Node catalog

Texture-like nodes expose Unreal-style **RGB / R / G / B / A** output pins;
most math nodes have a single Out pin.

| Category | Nodes |
| --- | --- |
| Particles | Particle Color (RGB/R/G/B/A), Particle Relative Time, Particle Speed, Particle Random, Particle Size, Particle Direction, Particle Position, Particle Macro UV, DynamicParameter (four named channels fed by the Shader Custom Data module) |
| Constants | Constant (Float / Vec2 / Vec3 / Color), Time, Gradient Ramp (full gradient editor on the node) |
| Coordinates | Texture Coordinate, Tiling & Offset, Rotator, Panner |
| Math | Multiply, Add, Subtract, Divide, Lerp, One Minus, Clamp, Step, Smoothstep, Power, Min, Max, Remap, Desaturate, Fresnel (radial), Sphere Mask, Split, Combine, Swizzle, Abs, Frac, Floor, Ceil, Round, Sign, Square Root, Length, Normalize, Dot Product, Sine, Cosine, If |
| Texture | Texture Sample (RGB/R/G/B/A), ParticleSubUV (flipbook-aware sampling) |
| Utility | Noise (Value / Fast Gradient / Perlin Gradient / Simplex / Voronoi, with turbulence, octave levels, tiling, seed, and bake size — baked to textures at compile time), Vector Noise (Cellnoise / Perlin 3D / Perlin Gradient / Perlin Curl / Voronoi), AntialiasedTextureMask, SphericalParticleOpacity |
| Parameters | Parameter (references a declared parameter), Subgraph |
| Output | Output — baseColor, emissive, opacity, opacityMask inputs (always present, one per graph) |

### Material settings

| Setting | Options | Notes |
| --- | --- | --- |
| Blend | Normal (Translucent) · Additive · Masked (Cutout) · Opaque | Masked and Opaque are material-authoritative: they override the emitter's blend mode (which then shows "Driven by material."). |
| Opacity Mask Clip | 0–1 | Default 0.333. The cutout threshold; active for Masked blending or when an Opacity Mask output is wired. |
| Render Faces | Both (Two-Sided) · Front Only · Back Only | Applies to the Three backend (Pixi flat particles have no back-face culling). For convex transparent meshes, Front Only avoids back-faces showing through. |

### Parameters and material instances

The inspector's **Parameters** section declares typed inputs — `float`,
`vec2`, `vec3`, `color`, `texture`, `bool` — with a display group, a
Per-material or Global scope, an optional slider range (floats), and an
optional **Per-particle** flag (floats; feeds DynamicParameter).

An emitter binds a material through the Renderer module's **Surface** row.
What the emitter stores is a **material instance**: the graph reference plus
per-instance parameter overrides and an optional **MainTex override** — so
one graph can drive many emitters with different textures and settings.
Overridden rows get a reset button ("Reset to default") that returns them to
the graph's live default.

### Tiers: how materials run on each backend

The meter strip under the graph reports the compiled **Tier**, the
texture-tap count (warns above 3), the shader program count, and any
per-particle inputs:

| Tier | Meaning |
| --- | --- |
| 0 · Baked | The graph is static per texel and is baked into a texture at author time — free at runtime. |
| 1 · Fixed-function | Resolves to tint / emissive / opacity uniforms and vertex-stage UV animation on the shared sprite shader — unlimited variants at no shader cost. |
| 2 · Uber-shader | Real per-pixel or per-particle math compiled into a dedicated shader program. Triggered by particle nodes, DynamicParameter, per-particle parameters, time-driven UV used outside a texture input, or fragment ops fed by dynamic inputs. Pixi runs Tier 2 through its batched particle path; Three compiles full shaders. |
| 3 · Deferred | Reserved for node types the runtime cannot render yet; exported as data-only. No node in the current palette produces Tier 3. |

## Exporting for games

The inspector's **Validation & Export** module shows the current effect's
validation summary (blockers, errors, warnings) and the **Export Game VFX**
button, which exports the whole project. Right-clicking an effect file in
the Assets browser offers a single-effect **Export Game VFX** as well.

Export writes the project's output folder (default `out/vfx`):

```
out/vfx/
  manifest.json     # effect + asset index, validation status
  effects/*.json    # compiled effects with per-backend support reports
  ...               # byte-copies of every referenced texture/mesh/material
```

- Every compiled effect (and its manifest entry) carries a `support` report
  per backend — `supported`, `partial`, or `blocked` — with warnings and
  blockers, so a game can fail fast on effects its renderer cannot honor.
- If validation blocks the export, the editor writes
  `export-diagnostics.json` instead of a bundle and lists the diagnostics in
  the panel.
- **The output folder is emptied and rewritten on every export** — never
  keep hand-made files in it.
- The result panel reports the outcome ("Exported N effects to out/vfx.",
  "…with partial-support warnings.", or "Export blocked for N effects.")
  with the written files and any diagnostics.

Loading the bundle in a game is covered by the runtime feature reference
(https://nixiefx.com/vfx-runtime-docs/) and the Three.js runtime guide
(https://nixiefx.com/threejs-runtime/): install `nixie-fx` with your
renderer, load the bundle, and drive `update()` from your frame loop.

## Keyboard shortcuts

| Keys | Where | Action |
| --- | --- | --- |
| Ctrl/Cmd+S | VFX view | Save the current effect |
| Ctrl/Cmd+Z | VFX view / Materials view | Undo |
| Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y | VFX view / Materials view | Redo |
| Esc | everywhere | Close the open dialog, popover, or menu |
| Ctrl/Cmd+A / C / V / D | Assets browser | Select all / copy / paste / duplicate |
| F2 | Assets browser | Rename the selected item |
| Delete or Ctrl/Cmd+Backspace | Assets browser | Delete the selection (with confirmation) |
| Arrows, Home/End, PageUp/PageDown, type-ahead | Assets browser file view | Move the cursor; Enter opens, Space selects |
| Ctrl/Cmd+C / V / D, Delete | Material graph | Copy / paste / duplicate / delete nodes |
| Alt+click | Material graph pins and edges | Break connections |
| Delete / Backspace | Curve / gradient editors | Remove selected points or stops |
| Shift (held) | Any drag-scrub number field | Fine control (0.1× sensitivity) |
| Ctrl/Cmd+wheel | Timeline lanes | Zoom the timeline |
| Enter / Esc | Any inline editor | Commit / cancel |

There is no spacebar play/pause and no export shortcut. The save shortcut
applies only in the VFX view — materials save with their toolbar button.

## Troubleshooting & FAQ

### Which browsers does the editor support?

Chromium-based browsers: Chrome, Edge, Arc, Brave, Opera. The editor needs
the File System Access API to read and write your project folder; Safari and
Firefox do not ship it yet.

### Where do my files live? Is anything uploaded?

Everything lives in the project folder you picked — effects as `.json`,
materials as `.material`, exports under `out/vfx`. Nothing is uploaded. The
browser stores only the project list, per-project UI state (camera, bloom,
panel sizes), and the folder handles it needs to reopen your projects.

### The editor keeps asking for folder permission. Why?

Browsers expire folder permissions periodically. The editor re-requests
access when it needs it — for the playground it shows "Folder access needed"
and asks again; for regular projects the permission prompt appears when you
reopen them. If a folder was moved or deleted, pick it again.

### My playground disappeared. What happened?

The playground is a normal folder on disk. If the folder was deleted or
emptied, the playground card restarts setup and asks you to pick a new empty
folder.

### Why is the Blend Mode dropdown grayed out?

The emitter's surface is driven by a material whose blend mode is
authoritative ("Driven by material."). Change the blend in the material's
inspector, or switch the Surface row back to Texture.

### Why does one backend's dot show a warning or blocker?

Some features are backend-specific: prepared 3D mesh particles, mesh-surface
emission, and lit shading need the Three backend; sub-emitters currently run
on Pixi only; Pixi approximates GPU depth writing with deterministic 2.5D
ordering. The dot's tooltip names the first issue, and the Validation &
Export panel lists them all. A blocked effect still previews on the other
backend and exports with an explicit blocked status.

### My export produced only export-diagnostics.json.

Validation blocked the export. Open the effect, check the Validation &
Export panel, and fix the listed blockers. Every export first empties the
output folder, so a blocked export leaves only the diagnostics file.

### What does "N missing asset refs" in the Assets tab mean?

A saved effect references a texture or mesh path that no longer resolves —
usually after a file was moved or renamed outside the editor. Select
textures to see their "Referenced by" lists, or re-assign the texture on the
affected emitter.

### Does the preview match the game exactly?

The preview embeds the same runtime games use, with the same deterministic
simulation — same seed, same motion. Preview bloom and the preview
background are editor-side aids and are not exported.

## Resources

- Editor: https://nixiefx.com/editor/
- Feature reference: https://nixiefx.com/vfx-runtime-docs/
- Three.js runtime guide: https://nixiefx.com/threejs-runtime/
- Runtime repository (MIT): https://github.com/azakhary/nixie-fx
- npm package: https://www.npmjs.com/package/nixie-fx
- Agent skills: https://nixiefx.com/skills/

*This manual is maintained by the team behind NixieFX, the browser-based
particle editor for PixiJS and Three.js. The HTML version with screenshots
lives at https://nixiefx.com/editor-manual/, and a site index for LLMs at
https://nixiefx.com/llms.txt.*
