This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
API Reference
The API is available as the global leanFX and as game.modules.get("leanFX").api, from Foundry's init hook on. Both are the same frozen object.
const api = game.modules.get("leanFX")?.api; // in a module; undefined if leanFX is not active
Targets
Every method that takes a target accepts:
- a placeable:
canvas.tokens.controlled[0], a Tile, Drawing or Region object; - its document:
token.document,scene.tiles.get(id); - the document's full UUID:
"Scene.abc.Token.def".
Only Tokens, Tiles, Drawings and Regions that belong to a Scene are valid. Bare IDs are rejected. Documents in a scene nobody is viewing can still be changed; the effect appears once the scene is drawn.
Filter specs
A spec is a plain object describing one filter instance:
{filterType: "glow", filterId: "ward", color: 0x66ccff, outerStrength: 4}
filterType is one of the 45 filters; filterId names this instance on the document. All other keys are the filter's parameters or the common fields described in Filter Specs. Unknown keys are rejected. Specs are copied; leanFX never modifies the objects you pass.
Saving effects
All of these return a Promise. It resolves once the GM has saved the change, with the document's complete effect list afterwards (an array of specs). It rejects with an Error whose message starts with leanFX | when the input is invalid, you lack permission, or no GM is connected. Nothing is saved when an operation fails.
| Method | What it does |
|---|---|
addFilters(target, specs, options?) |
Adds new filters. Fails if a filterId already exists on the document. |
addUpdateFilters(target, specs, options?) |
Adds filters whose filterId is new and updates the ones that exist. The usual choice. |
updateFilters(target, specs, options?) |
Updates existing filters. Fails if a filterId does not exist. |
deleteFilters(target, filterId) |
Deletes one filter. A missing ID is not an error. |
deleteFilters(target) |
Deletes all leanFX filters from the document. |
specs is an array of 1–32 specs with unique filterIds. A document holds at most 32 filters.
deleteFilters(target) also repairs unreadable or obsolete leanFX flags. Targeted deletion removes only the matching ID and does not require unrelated saved entries to be valid. Automatic expiry leaves malformed data alone. Expired one-shot entries are reclaimed before add/upsert/update operations check IDs and capacity.
After the last entry is removed, flags.leanFX.effects retains an empty {schema, revision, effects: []} envelope. No effect specs or start times remain. Optional regionRendering settings are retained alongside the empty stack. Verify the saved effects array, rather than expecting the whole flag key to be unset.
Updates merge. In addUpdateFilters and updateFilters, only the keys you pass change; the rest of the saved spec stays. Two rules:
filterTypemust be given and must match the saved filter. To change the type, delete the filter and add a new one.animatedis replaced as a whole and restarts the filter's animation. Passanimated: {}to stop all animation. Other changes keep the running animation in step.
For onComplete: "delete", every active animation must be finite. To stop its animation and keep a static filter, update with both onComplete: "hold" and animated: {}. Use addUpdateFilters to replay a one-shot that may already have expired.
const token = canvas.tokens.controlled[0];
await leanFX.addUpdateFilters(token, [{filterType: "glow", filterId: "ward", color: 0x66ccff}]);
await leanFX.updateFilters(token, [{filterType: "glow", filterId: "ward", outerStrength: 8}]); // color stays
await leanFX.updateFilters(token, [{filterType: "glow", filterId: "ward", enabled: false}]); // hide, keep it
await leanFX.deleteFilters(token, "ward");
On the selection
These run the operation on every controlled placeable of the active layer (Tokens on the Token layer, Tiles on the Tile layer, and so on). They reject when nothing is selected and resolve with an array of results, one per placeable. Each placeable is saved separately: if one fails, the others may already be saved.
| Method | Same as |
|---|---|
addFiltersOnSelected(specs, options?) |
addFilters |
addUpdateFiltersOnSelected(specs, options?) |
addUpdateFilters |
updateFiltersOnSelected(specs, options?) |
updateFilters |
deleteFiltersOnSelected(filterId?) |
deleteFilters |
getControlledPlaceables() |
Returns the placeables these methods would use. |
For targeted tokens, loop over game.user.targets (see Examples).
Region rendering
For Regions, filter saves accept optional {placement, backdrop, rotate} as a third argument; selection helpers take it as their second argument. Filters and rendering save atomically. Given options merge into the saved ones; omitted options keep their saved value. Other target types reject rendering options. Rendering applies to the whole Region stack, separately from shader parameters and zOrder. backdrop: true requires a scene placement. See Region rendering.
| Method | Returns |
|---|---|
setRegionRendering(target, options) |
Promise resolving to saved rendering options, without changing filters or restarting animations. |
getRegionRendering(target) |
A copy of saved options, {placement, backdrop, rotate}, with unset values resolved to "interface", false and false. Excludes previews. |
Accepted values are "interface" (default), "ground", "aboveTiles" and "aboveTokens". Deletion and expiry retain rendering settings. Preview accepts the same optional third argument locally. See Region rendering for examples, elevation, lighting and visibility.
Reading effects
| Method | Returns |
|---|---|
getFilters(target) |
A copy of the saved specs (array). Previews are not included. |
hasFilterId(target, filterId) |
true if a saved filter has this ID. |
hasFilterType(target, filterType) |
true if a saved filter has this type. |
Previews
const handle = leanFX.preview(token, [{filterType: "xglow", filterId: "try", color: 0xff8800, auraType: 2}]);
// ... look at it ...
handle.clear();
preview(target, specs, options?) shows specs on this client only, without saving anything. The saved effects of that object are hidden while the preview is shown. It returns a handle with clear(); clearPreview(target) clears whatever preview the object has. A newer preview replaces an older one, and an old handle cannot clear a newer preview. Saved changes made meanwhile appear when the preview is cleared. The target must be drawn on the scene you are viewing.
Preview filters accept onComplete: "delete" too. When the last preview filter expires, the current saved effects return automatically.
Diagnostics
| Method | Returns |
|---|---|
inspect(target) |
{uuid, drawn, resolutionCap, preview, loading, filters, errors} for one drawn object. filters lists the rendered filters (filterId, filterType, animating); errors lists filters that were skipped and why (invalid saved data, image failed to load, shader failed to compile on this GPU). loading is true while images load. resolutionCap is the highest render resolution the object's filters may use right now, or null when there is no limit (see large objects). |
diagnostics() |
{objects, filters, tickerAttached, previews} for the whole canvas on this client. |
refresh(target) |
Rebuilds the object's filters on this client. Saves nothing. |
For Regions, inspect() also includes regionRendering: {placement, backdrop, rotate, elevation, visible, backdropCaptured, turned}, or null without a mesh. Invalid rendering metadata appears in errors and suppresses the overlay until repaired.
Discovery
| Property or method | Value |
|---|---|
version |
The installed leanFX version. |
filterTypes |
The 45 filter type names. |
animationModes |
The 19 animation mode names. |
regionPlacements |
The four accepted Region placement names. |
parameters(filterType) |
The filter's own parameter names (without the common fields). |