Team Cereustooling wiki

Take batch screenshots of a character with DSAS

Partly checkedagainst the code on 2026-11-12 11:45

"DS ANIM STUDIO.exe" --auto job.json opens one character, scrubs to each animation and time you list, saves a PNG of the 3D view each time, writes a log and exits. No splash, no Welcome window, no folder picker, no model picker.

Status partial: the job format, the log lines and the code paths were read from the source. DSAS was not built or run for this page. The tips under "Notes from earlier runs" are dated team notes.

Before you start

  • The built exe: S:\_modding\tools\DSAnimStudio\DSAnimStudioNETCore\bin\Release\net9.0-windows7.0\DS ANIM STUDIO.exe. It exists as of 2026-11-12, with oo2core_9_win64.dll beside it.

  • To rebuild after a source change (heavy, run it through eb.py run --mem):

    dotnet build DSAnimStudioNETCore\DSAnimStudioNETCore.csproj -c Release
    

    from S:\_modding\tools\DSAnimStudio. A fresh output folder needs oo2core_9_win64.dll copied in; the fork's install\ folder is where the team note says to take it from.

  • The character's files: an anibnd (cXXXX.anibnd.dcx) and a chrbnd (cXXXX.chrbnd.dcx).

  • A mod folder that holds them the way the game would see them (<mod>\chr\...). DSAS finds files through the mod folder in the workspace file, not through the path you opened.

Steps

  1. Write _DSAS_WORKSPACE.json in the same folder as the anibnd. The folder picker is skipped in batch mode, so this file must already point at the game and the mod:

    {
      "GameDirectory": "S:\\SteamLibrary\\steamapps\\common\\ELDEN RING NIGHTREIGN\\Game",
      "ModEngineDirectory": "S:\\path\\to\\the\\mod",
      "LoadLooseParams": false,
      "LoadUnpackedGameFiles": false,
      "DisableInterrootDCX": false
    }
    

    Write it with a file tool or Python. A bash heredoc eats the backslashes.

  2. Write the job file. The smallest useful one:

    {
      "ani": "S:\\path\\to\\the\\mod\\chr\\c9700.anibnd.dcx",
      "chr": "S:\\path\\to\\the\\mod\\chr\\c9700.chrbnd.dcx",
      "out": "S:\\path\\to\\out",
      "anims": [3000, 3001],
      "times": [0, 0.5]
    }
    

    Field names are not case-sensitive. Every field is in the reference. The ones you need most:

    • anims: full animation ids as numbers (a000_003000 is 3000).
    • times: seconds into each animation. Default [0].
    • anims empty: one picture, loaded.png, of the model as it loads.
  3. Run it:

    "S:\_modding\tools\DSAnimStudio\DSAnimStudioNETCore\bin\Release\net9.0-windows7.0\DS ANIM STUDIO.exe" --auto S:\path\to\job.json
    

    A window opens, sized to width by height + 60. It closes by itself when the job is done.

  4. Read the results in the out folder:

    • a<9-digit anim id>_t<time with 3 decimals>.png, for example a000003000_t0.500.png;
    • auto.log.

For a clean portrait

Add these to the job:

{
  "hideHelpers": true,
  "background": [40, 40, 40],
  "autoFrame": true,
  "margin": 0.06,
  "yaw": 20,
  "pitch": 5
}
  • hideHelpers hides the grid, bones, dummy polys and hit capsules.
  • background sets a flat colour and turns the skybox off. autoFrame needs a flat background: it finds the model by looking for pixels that differ from the border colour.
  • autoFrame moves and zooms the camera until the model fills the view minus margin.
  • To render the same camera twice (for example with some meshes hidden), copy dist and center from the first run's fixed camera or last frame log line into camDist and camCenter.

Reading auto.log

Each line is [HH:mm:ss.fff] <category>: <message>.

Line Meaning
AUTO: job ani=... chr=... anims=... times=... The job as read.
AUTO: model <name> meshes=N bones=N hkxBones=N One per loaded model. hkxBones is the animation skeleton's bone count.
MESH: <model> [i] mask=N mat='...' mtd='...' Every submesh: index, model mask, material. Use these for the hide options.
SLOT: and PART: c0000 only: equipment slots and the part models loaded for them.
AUTO: anim a000003000 found=True The animation was found. found=False skips it.
AUTO: t=0.5 (max 2.133) The scrub time and the animation's length.
AUTO: frame N: bounds=... edge=... -> dist=... center=... One auto-frame step.
AUTO: saved a000003000_t0.500.png A picture was written.
AUTO: capture failed: ... The picture could not be written.
AUTO: timed out waiting for the anibnd/model to load Nothing loaded within openTimeoutFrames.
AUTO: equip: the model has no ChrAsm (not c0000?) equip was set on a non-human character.
NOTIF/<type>: ... A DSAS notification.
DIALOG: auto-closed '<title>': <text> A native dialog popped up and was closed for you. Read its text: it is usually the real error.
AUTO: done The job finished.

Other categories are DSAS's own error log lines.

What goes wrong

  • No pictures, and a DIALOG or "Failed to load animations" line; or hkxBones=0. The anibnd is broken or has no skeleton. Team note (2026-10-24): hkxBones=0 means a broken anibnd.
  • Timed out. The workspace file is missing or wrong, so the game files were not found.
  • The character is white. Its materials were not found. In batch mode DSAS also reads loose material\matbin\<name>.matbin files from the mod folder. Team note (2026-10-30): ported characters render white unless their matbins are staged in the mod's material folder.
  • found=False for every animation. The anibnd has no TAE for this character. Team note: some characters share a parent's anibnd; set ani to the parent's.
  • The window stays open. exit is false, or the job never reached done.
  • The user's DSAS layout looks broken after a batch run. This was a bug in an early version of the fork. The fork now gives ImGui no ini file and skips the config save whenever --auto is on the command line. If it happens again, check that the exe is the fork's build.

Notes from earlier runs (team memory, 2026-10-30)

Not confirmed for this page.

  • DS ports look right with sceneBrightness around 1.5. Elden Ring and NR characters look right at the defaults.
  • DS3 fur and some hair or cloth cards render as white planes: hide them with hideMaterials or hideSubmeshes.
  • To show one variant of a model, take its mask set from the source game's NpcParam (modelDispMask*) and pass it as showMasks.
Source files this page documents (5)
  • modding:DSAnimStudio/DSAnimStudioNETCore/DSASAutomation.cs
  • modding:DSAnimStudio/DSAnimStudioNETCore/zzz_GameRootIns.cs
  • modding:DSAnimStudio/DSAnimStudioNETCore/TaeEditor/TaeProjectJson.cs
  • modding:DSAnimStudio/DSAnimStudioNETCore/FlverMaterialDefInfo.cs
  • modding:DSAnimStudio/DSAnimStudioNETCore/Main.cs

Changed one of these? Update this page: dsas/render-a-character.md (how).