Programmatic API
The module exposes an API on window.Tokenizer2 and game.modules.get("tokenizer-2").api once the tokenizer-2.ready hook fires.
Functions
| Method | Purpose |
|---|---|
openEditor(actor, token?) | Open the editor for an existing actor (the same entry the portrait click uses) |
openEditorStandalone(opts) | Open the editor with no actor - for flows that compose art before an actor exists |
tokenize(actor, opts?) | Headless single-actor tokenize (no UI) |
tokenizeBatch(actors, opts?) | Headless batch tokenize |
exportLayers(layers, opts?) | Render a layer stack to a blob/dataURL |
promptConfig(opts?) | Show a config dialog; resolves to a config object suitable for tokenize() (or null if cancelled) |
openEditorStandalone(options)
Opens the full editor without an Actor document. Saves still render and upload the image(s) to disk, but nothing is written to a document - instead the generated paths and the prototype-token patch are returned so the caller can apply them to an actor it creates afterward. Designed for character-creation wizards (e.g. Hero Mancer) that let the user pick portrait/token art before the actor is created.
const result = await game.modules.get("tokenizer-2").api.openEditorStandalone({
name: "Aria the Wizard", // drives the save filename
type: "character", // "character"/"pc" route to the PC save folder
sourceImage: "path/to/portrait.png",
// optional:
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY, // default-ring selection
hasPlayerOwner: true, // overrides PC detection (defaults true for character/pc)
targetFolder: "[data] my/folder",// overrides the configured pc/npc save location
userId: game.user.id, // advisory - used only for a FILES_UPLOAD permission check
onComplete: (res) => console.log(res),
});
Returns a Promise that resolves when the editor closes (the onComplete callback fires with the same value):
- On save, an object:
{ tokenPath?, avatarPath?, prototypeToken?, avatarUpdate?, layerStack }tokenPath/avatarPath- server paths of the uploaded image(s)prototypeToken- a dotted patch (prototypeToken.texture.src,.texture.scaleX/Y, and in dynamic-ring modeprototypeToken.ring.*) to apply to the new actoravatarUpdate-{ [avatarKey]: path }patch for the actor's portrait fieldlayerStack- the serialised layer stack, to store as a flag for future non-destructive re-edits
- On close without saving,
null.
Recipe for applying the result to a freshly-created actor:
if (result) {
await actor.update({ ...result.prototypeToken, ...result.avatarUpdate });
await actor.setFlag("tokenizer-2", "layerStack", result.layerStack);
// Opening Tokenizer 2 on this actor later rehydrates the saved composition.
}
Notes
- Only one editor can be open at a time; calling this closes any open editor first.
- Files are written to the configured PC/NPC save locations (by
type) unlesstargetFolderis supplied; the in-editor Save dialog still lets the user tweak folder/filename. - The default ring is applied only if the Apply Default Ring setting is enabled; a standalone actor has no real disposition, so it defaults to friendly (or the supplied
disposition).
promptConfig(options)
Shows the same options form as the compendium auto-tokenizer (frame, mask, portrait fit, image source, wildcard handling, save folder) but returns the chosen settings instead of running a batch. Designed for external modules (e.g. DDB Importer) that prompt the user once and apply the same config to many imported actors.
const api = game.modules.get("tokenizer-2").api;
const config = await api.promptConfig({
defaults: { saveFolder: "[data] tokenizer/imports" }, // optional
// title: "...", description: "...", previewActor: someActor,
});
if (!config) return; // user cancelled
for (const actor of importedActors) {
await api.tokenize(actor, { ...config, filename: actor.name });
}
Returns Promise<object|null> - the object has the same shape as tokenize() options (forceDynamicRing, forceBakedRing, frameSrc, maskSrc, portraitFit, useActorImg, wildcardMode, saveFolder) and can be spread directly into tokenize(). The preview uses a synthetic standalone actor when no previewActor is supplied.
Pre-creation use: tokenize(actorData, { updateActor: false })
tokenize() can also be used before an actor document exists - for example, when DDB Importer assembles a monster's actor-data and wants to embed the rendered token into that data before calling Actor.create(). Pass updateActor: false to skip every actor mutation while still uploading the file:
const api = game.modules.get("tokenizer-2").api;
const cfg = await api.promptConfig({ defaults: { saveFolder: "[data] imports/tokens" } });
const { path, prototypeToken, layers } = await api.tokenize(actorData, {
...cfg,
filename: actorData.name,
updateActor: false,
});
// Merge the patch into the actor-data being assembled. The keys are dotted, so
// expand before merging.
foundry.utils.mergeObject(actorData, foundry.utils.expandObject(prototypeToken));
actorData.flags ??= {};
actorData.flags["tokenizer-2"] = { layerStack: layers };
await Actor.create(actorData);
With updateActor: false:
- The blob is still uploaded to the configured (or supplied) save folder.
actor.update,actor.setFlag, and the placed-token patch are all skipped.result.prototypeTokencarries the exact dotted-key patch that the writes would have used, including the cache-bustedprototypeToken.texture.src.result.layersis the serialised layer stack, ready forsetFlagor merging intoflags["tokenizer-2"].layerStack.