Native .elybrush format¶
.elybrush is the Designer's portable brush file. One file holds a
complete preset (engine + parameters + dynamics curves + optional
texture / pattern image). Built-in presets, Studio-saved presets,
and .abr / .sut imports all live in this format.
Why a custom format¶
- One file per preset: trivial to share, version-control, and rsync across machines.
- Forward-compatible JSON wrapper: Designer versions ignore fields they do not understand instead of refusing to load.
- Embeddable images: textures and pattern stamps base64-embed into the same file (or reference an external PNG when the user prefers).
File anatomy¶
A .elybrush is a JSON document (.elybrush is the extension; the
content is text). Minimal example:
{
"schema_version": "1.0",
"id": "ely.builtin.pencil",
"name": "Pencil",
"engine": "round_stamp",
"params": {
"size_px": 4,
"opacity": 0.7,
"hardness": 0.95,
"spacing": 0.18
},
"dynamics": {
"size_px": {
"channel": "pressure",
"curve": [[0.0, 0.1], [0.5, 0.5], [1.0, 1.0]]
},
"opacity": {
"channel": "pressure",
"curve": [[0.0, 0.2], [1.0, 1.0]]
}
},
"tags": ["sketch", "dry"],
"color": "#222222ff",
"thumbnail": "data:image/png;base64,iVBORw0KGgo..."
}
Top-level fields¶
| Field | Required | Notes |
|---|---|---|
schema_version |
Yes | "1.0" today. Loader rejects schema versions it does not recognize. |
id |
Yes | Globally unique. Built-ins use ely.builtin.*. User presets use user.<machine_id>.<uuid>. |
name |
Yes | Display name |
engine |
Yes | One of round_stamp / airbrush / bristle / texture / pattern / wet_mix / a registered custom engine id |
params |
Yes | Engine-specific parameter values (see Engines reference) |
dynamics |
No | Per-parameter input channel + curve |
tags |
No | Free-form list of strings; used by Library filter |
color |
No | Default color (CSS hex #rrggbbaa) |
thumbnail |
No | Base64 PNG (typically 96 x 96); auto-generated if missing |
texture |
No | Embedded texture image for Texture/Pattern engines |
notes |
No | Free-form user notes |
source |
No | Provenance: { "kind": "abr", "file": "name.abr" } for imported brushes |
dynamics shape¶
"dynamics": {
"size_px": {
"channel": "pressure", // pressure | tilt | rotation | velocity | altitude | distance | random
"curve": [[0.0, 0.1], [0.5, 0.5], [1.0, 1.0]]
}
}
channelis one of the seven dynamics input channels.curveis a list of[input, multiplier]pairs, monotonic oninput, evaluated by linear interpolation.
texture shape¶
"texture": {
"embed": true,
"data": "data:image/png;base64,iVBORw0KGgo...",
"scale": 1.0,
"rotation_deg": 0,
"offset_x": 0,
"offset_y": 0
}
embed: false stores data: "textures/foliage_stamp.png" instead
of base64, resolved relative to the .elybrush file's parent
directory. Useful when sharing a folder of brushes together rather
than as individual files.
Versioning¶
Schema versions are major-numbered. The 1.x line is forward-
compatible: a .elybrush saved with a newer Designer that adds
fields will load in an older Designer (the new fields are
ignored). A 2.0 schema would be a breaking change with a
migration tool.
Validation¶
The Designer validates every .elybrush on load:
- Engine id must exist (built-in or registered Python engine).
- Parameter names must be valid for that engine.
- Curves must be monotonic on x.
- Embedded textures must be valid PNG / JPG / WebP.
Validation failures are surfaced as a Library entry with a warning icon and a one-line explanation; the preset is still loadable but flagged as suspect.
Tooling¶
A small CLI ships with the framework:
elybrush inspect mybrush.elybrush # prints a summary
elybrush diff a.elybrush b.elybrush # field-level diff
elybrush minify mybrush.elybrush # strip thumbnails, compact JSON
elybrush extract mybrush.elybrush # write the embedded texture to a .png
Useful for inspecting third-party brush packs or pruning size from brushes destined for a shared distribution.
On disk¶
The user library at <user_dir>/brushes/user/ holds one
.elybrush per preset. The built-in library at
<install>/python/elysium/brush/builtin/ is read-only; copy a
built-in into the user folder via the Library's right-click menu
to derive from it.