Files
wtd-libreflow-addon/README.md
T
Nero Frame 13andClaude Opus 5.5 00788bb3bf Shot Viewer: sequence field, cameras named CAM_sq0000_sh0000
The Shot Viewer panel gets a Sequence number, saved with the scene. New
shot cameras are named from it with SHOT_CAMERA_NAME_FORMAT
("{prefix}{sequence}_{shot}") and SEQUENCE_NAME_FORMAT ("sq{:04d}"),
both overridable in the config JSON.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 13:25:09 +02:00

20 KiB
Raw Blame History

Melvile Tools

Blender add-on for the Melvile pipeline (Walking The Dog). It brings together:

  • Sanity Check: checks a file against the production specs and fixes what can be fixed.
  • Rename: batch renames objects and materials to the naming convention, with consistent numbering.
  • Shot Viewer: switch, create and delete the shots of a sequence (camera markers) from the sidebar, with quick access to the character and prop rigs.
  • Get Oid: asks Libreflow for the id of the open file.

Most values the tools rely on (prefixes, shot naming, frame rate…) live in config.py and can be overridden per studio without touching the code. See Configuration.


Contents


Installation

Tested on Blender 5.2.

As an extension (artists): build the package, then in Blender go to Edit > Preferences > Get Extensions > Install from Disk… and pick the .zip.

blender --command extension build --source-dir path/to/wtd-libreflow-addon

From source (development): put the wtd-libreflow-addon folder in the addons folder of your Blender scripts directory, then enable Melvile Tools in Edit > Preferences > Add-ons. Reload Scripts (F3) picks up code changes in every file.

Preferences

Edit > Preferences > Add-ons > Melvile Tools:

Setting Use
Character Reference JSON file exported from the master character, used by the character checks (see Character reference). Falls back to the WTD_CHAR_REFERENCE environment variable.
Config Override JSON file overriding values of config.py (see Configuration). Falls back to the WTD_SANITY_CONFIG environment variable.

Where to find the tools

Open the sidebar of the 3D Viewport (N) and click the WTD tab.

Panel Editors
Sanity Check 3D Viewport, Video Sequencer
Tools (Get Oid) 3D Viewport
Rename 3D Viewport, Shader Editor
Shot Viewer 3D Viewport

Sanity Check

Checks the open file against the specs of a production context (the kind of file it is), reports the problems and fixes the ones that can be fixed automatically.

Quick start

  1. Pick the context at the top of the panel (for example Asset: General or Shot: Layout).
  2. For asset contexts, the Asset name is read from the file name. Type it in if the file is not named yet.
  3. Click Run Checks.
  4. Click Fix All to fix everything that can be fixed, then look at what is left.

The counters under the buttons sum up the result: passed, warnings, errors, skipped and crashed checks.

Contexts

Context For File name expected
Asset: General Props, sets, generic assets (modeling and lineart) prp_name_mod.blend, set_name_lineart_v002.blend…
Character: Modeling Character modeling chr_name_mod.blend
Character: Lineart / Shading Character lineart and shading chr_name_lineart.blend, chr_name_shading.blend
Shot: Layout Shot layout sq010_sh0010_layout.blend
Shot: Animation Shot animation No checks yet

The context and the disabled checks are saved in the .blend.

Buttons

Button Action
Run Checks Runs every enabled check of the context.
Fix All Runs the fix of every failing check that has one, then runs all checks again.
Report icon (right of Fix All) Writes the last report to the text datablock WTD_Sanity_Report (open it in the Text Editor). Useful when there are more issues than the panel shows.
Export Character Reference Character: Modeling only. See Character reference.

On each check row:

Element Action
Checkbox Enables or disables the check for this file.
Arrow Unfolds the description and the list of issues.
Status icon Not run, passed, info, warning, error, skipped or crashed. The number in brackets is the issue count.
Arrow-cursor icon Selects the objects of the issues. For geometry issues, it enters Edit Mode with the faulty vertices, edges or faces selected.
Wrench icon Fixes this check. It is shown only when the check failed and has a fix. Hover it to see what the fix does.
Refresh icon Runs this check only.

In the unfolded list, each issue has its own select button. For naming checks, the name can be edited right there.

Ctrl+Z undoes every fix.

Checks

✔ means the check has an automatic fix.

All contexts

Check What it checks Fix
Units Unit system, scale and length unit follow the specs. ✔
File name The file is saved and its name follows the pattern of the context.

Asset contexts (General, Character Modeling, Character Lineart / Shading)

Check What it checks Fix
Naming convention Objects, mesh data, collections, materials and node groups carry the type prefix (GEO_, COL_, MAT_…). No Blender default names (Cube, Material…), no .001, no spaces or accents. Mesh data is named like its object. ✔ when a name can be derived
Collection structure No object directly in the Scene Collection, no empty collection, the required collections exist. ✔ removes empty collections
N-gons Only triangles and quads.
Concave faces No concave quad or n-gon.
Non-manifold geometry No wire edges, edges with more than two faces, flipped normals, bow-tie vertices or open borders.
UVs Every mesh has a UV map and no negative UV coordinate.
Modifiers Only Subdivision Surface and Multiresolution. Lineart / Shading files also allow Line Art and Thickness. ✔ applies the others
Transforms applied Rotation and scale of geometry objects are applied. ✔
Unused nodes No node disconnected from the output in materials, worlds and node groups. ✔ deletes them
No animation No action or NLA track assigned (drivers are fine). ✔

Character: Modeling

Check What it checks Fix
Inner mouth & eyes naming Inner mouth and eye objects carry exactly the names of the reference character.
Body vertex order The body has the same vertex count and order as the reference character.
Body vertex groups The body has the required vertex groups. ✔ creates them empty

Character: Lineart / Shading

Check What it checks Fix
Color management Display, view transform, look, exposure, gamma and colorspaces follow the specs. ✔ (except the working space)

Shot: Layout

Check What it checks Fix
Frame rate Matches the production frame rate. ✔
Resolution Resolution, percentage and pixel aspect match the production format. ✔
Shot start / end The frame range matches production tracking. Skipped until the Libreflow / Kitsu connection is set up. ✔
Duplicated names No local datablock with a .001 suffix. ✔ when the base name is free
Set positions Instanced set collections sit at the world origin. ✔
Sound versions Sound files exist and are the latest published version. ✔
Sound track active Scene audio, sound strips and their channels are not muted. ✔

Character reference

The character checks compare each character to a master character:

  1. Open the master character file, set the context to Character: Modeling and make sure the asset name is right.
  2. Click Export Character Reference and save the JSON in a shared location.
  3. Set that file as Character Reference in the add-on preferences, or in the WTD_CHAR_REFERENCE environment variable for everyone.

Tools panel

Get Oid For Open Scene

Asks Libreflow for the object id (oid) of the open file and shows it in the status bar. Blender must have been started from Libreflow, so that the Kabaret connection is available.


Rename

Renames the selected objects, or their materials, following the production naming convention. Numbering stays consistent across renames.

Names are built from these parts, joined with _. Empty parts are left out:

prefix _ name _ side _ number _ suffix
GEO    _ box  _ center _ 001  _ mesh     →  GEO_box_center_001_mesh

Settings

Setting Use
Objects / Materials Rename the selected objects, or the materials used by the selected objects.
Name The new name. Leave it empty to keep each item's current name and only bring it to the convention: box2 becomes box_….
Prefix None, By Type (GEO_ for meshes, CRV_ for curves, MAT_ for materials… the same prefixes the Sanity Check expects) or Custom.
Side Orientation token: center, left, right, front, back, top, bottom, or none.
Suffix None, By Type (mesh, curve, mat…) or Custom.
Order The order numbers are given in: current name, or position along X, Y or Z. Ordering along an axis numbers a row of pillars from one end to the other.
Rename Data Objects only. Gives the object data (mesh, curve, light… Maya's "shape" node) the same name as its object.

The box under the Rename button previews every change (old name → new name) before you click.

Numbering

  • It continues after the existing names. Rename three objects to pillar and you get pillar_001 to pillar_003. Rename two more later and they become pillar_004 and pillar_005.
  • Each pattern counts separately. pillar_left_… and pillar_right_… each have their own numbers.
  • Renaming again is safe. Objects that already follow the pattern keep their number when ordered by name, and new ones are numbered after them. Ordering along X/Y/Z renumbers them all by position.
  • Items in a linked library also count, so local numbers never repeat a library's numbers.

Examples

Selection Settings Result
temp, temp2, whatever Name pillar, Prefix None pillar_001, pillar_002, pillar_003
two more objects same pillar_004, pillar_005
box, box2 Name empty, Side center, Suffix By Type box_center_001_mesh, box_center_002_mesh
same + Prefix By Type GEO_box_center_001_mesh…
materials of the selection Materials, Name wood, Prefix and Suffix By Type MAT_wood_001_mat…

Good to know

  • With Name empty, the tool strips the old prefix, side, number, suffix and .001, and trailing digits (box2 → box, GEO_box_center_002_mesh → box). A name like tree_v2 therefore becomes tree_v. Type the name in such cases.
  • Data shared by several objects (instances made with Alt+D) is renamed after the first of them, and only when all of them are being renamed.
  • Linked (library) objects and materials are not renamed.
  • Ctrl+Z undoes the rename.

Shot Viewer

A sidebar panel to go through the shots of a sequence in their camera. You can switch shots, add and delete them, and grab the character and prop rigs.

How shots are stored

The whole sequence lives in one scene:

  • Each shot is a timeline marker bound to a camera. To bind one by hand: select the camera, put the playhead on the marker, then Marker > Bind Camera to Markers (Ctrl+B) in the Timeline.
  • A shot runs from its marker to the frame before the next camera marker. The last shot runs to the scene's End frame.
  • Markers without a camera are ignored, so you can keep using them as notes.
  • Several shots can use the same camera.

During playback, Blender itself switches to the camera of each marker, so playing the scene plays the cut.

Where it is

3D Viewport sidebar (N) > WTD tab > Shot Viewer.

Choosing a shot in the panel moves the playhead to it and puts the 3D view you clicked in into that shot's camera view. Keep a Timeline open (for example at the bottom of the Layout workspace) to see the camera markers and where you are in the sequence.

The list always highlights the shot under the playhead. The file does not need any shots yet: add the first one with +.

Sequence

Set the sequence number in the Sequence field at the top of the panel. It is saved with the scene, and the formatted name is shown next to it (10 → sq0010). It is used to name the cameras of new shots: CAM_sq0010_sh0030. Both formats can be changed in the Configuration (SEQUENCE_NAME_FORMAT, SHOT_CAMERA_NAME_FORMAT).

Moving through the sequence

To… Do…
Jump to a shot Click it in the shot list (name, camera, frames). The playhead jumps to the first frame of the shot.
Go to the previous / next shot Previous / Next.
Find a shot by name The filter field at the bottom of the shot list.
Scrub the sequence Drag the playhead in the Timeline. The camera and the shot list follow.
Play one shot Tick Loop Shot and press play: playback loops on the shot under the playhead.
Play the whole sequence Press play with Loop Shot unticked (the default): the cameras switch at each marker.

Loop Shot works by setting the scene's preview range to the shot frames (the shaded part of the Timeline). It follows when you change shot. Unticking it turns the preview range off.

Adding a shot

Click + next to the shot list:

Setting Use
Name Pre-filled with the next free shot number (sh0010, sh0020…). This is the marker name.
Duration Length of the shot in frames.
New Camera On: creates the camera CAM_<sequence>_<shot> (its name is shown in the dialog), copying the lens and position of the current camera, so you start from the current framing. Off: pick an existing camera of the scene.

The shot is added at the end of the sequence and the scene's End frame grows to include it. The first shot starts at frame 1001, and the scene Start moves there too. The playhead and the 3D view then jump to the new shot.

New cameras go in the scene's top collection: move them into your camera collection if you have one.

Deleting a shot

Put the playhead on the shot (or select it in the list) and click −:

  • The shot's camera marker is removed.
  • Delete Camera (off by default): also deletes its camera, unless another shot uses it.
  • Deleting a shot in the middle: its frames go to the previous shot. Nothing is moved in time: the animation stays where it is, so cut or shift it by hand if the frames must disappear.
  • Deleting the last shot: the scene's End frame moves back to the end of the previous shot.

Ctrl+Z undoes adding and deleting shots.

Selecting rigs

The bottom of the panel lists the armatures of the scene, grouped into Characters, Props and Other:

  • Click a rig: selects it and enters Pose Mode.
  • Shift+click: adds it to the selection, to pose several rigs at once.
  • The rig(s) currently selected are highlighted.

A rig counts as a character or a prop when its name, one of its collections, or the library file it comes from starts with chr_ / prp_ (see SHOT_VIEWER_RIG_GROUPS in Configuration). Hidden rigs cannot be selected.


Configuration

All production values live in config.py. Values marked TODO there are placeholders waiting for the real production specs.

To change them without editing the code, write a JSON file with the keys to override and set it as Config Override in the add-on preferences, or in the WTD_SANITY_CONFIG environment variable. Dictionaries are merged with the defaults, so only the keys you change need to be listed. Every other value replaces the default.

{
  "FPS": 25,
  "RESOLUTION": [1920, 1080],
  "RENAME_SIDES": ["center", "left", "right"],
  "SHOT_FRAME_START": 1001,
  "SEQUENCE_NAME_FORMAT": "sq{:03d}",
  "SHOT_VIEWER_RIG_GROUPS": {
    "Characters": "(?i)^(?:chr|ch)[_-]"
  }
}

Unknown keys are ignored and reported in the system console.

Name formats use Python's str.format: "sq{:04d}" turns 10 into sq0010. SHOT_CAMERA_NAME_FORMAT takes the named tokens {prefix} (the camera prefix of OBJECT_PREFIXES, CAM_), {sequence} and {shot}. The default "{prefix}{sequence}_{shot}" gives CAM_sq0010_sh0030.

Keys by tool

Tool Keys
Sanity Check: scene FPS, FPS_BASE, RESOLUTION, RESOLUTION_PERCENTAGE, PIXEL_ASPECT, UNIT_SYSTEM, UNIT_SCALE_LENGTH, UNIT_LENGTH, COLOR_MANAGEMENT
Sanity Check: files FILENAME_PATTERNS, VERSION_PATTERN
Sanity Check: naming OBJECT_PREFIXES, DATABLOCK_PREFIXES, NAME_BODY_PATTERN, MESH_DATA_MATCHES_OBJECT, DEFAULT_NAMES, DUPLICATE_NAME_TYPES
Sanity Check: assets REQUIRED_COLLECTIONS, MAX_FACE_SIDES, CONCAVE_TOLERANCE, NON_MANIFOLD_ALLOW_BOUNDARY, UV_NEGATIVE_TOLERANCE, ALLOWED_MODIFIERS, ALLOWED_MODIFIERS_LINEART, APPLY_TRANSFORM, APPLY_TRANSFORM_TYPES, TRANSFORM_TOLERANCE, FORBIDDEN_ASSET_OBJECT_TYPES
Sanity Check: characters CHAR_REFERENCE_PATH, CHAR_BODY_NAME, CHAR_PART_KEYWORDS, CHAR_BODY_VERTEX_GROUPS
Sanity Check: layout SET_COLLECTION_PATTERN
Sanity Check: panel CATEGORY_ORDER, MAX_ISSUES_DRAWN
Rename RENAME_SEPARATOR, RENAME_PADDING, RENAME_SIDES, RENAME_TYPE_SUFFIXES (plus OBJECT_PREFIXES / DATABLOCK_PREFIXES for By Type prefixes)
Shot Viewer SHOT_VIEWER_RIG_GROUPS, SHOT_NAME_FORMAT, SHOT_NUMBER_STEP, SHOT_FRAME_START, SHOT_DEFAULT_DURATION, SEQUENCE_NAME_FORMAT, SHOT_CAMERA_NAME_FORMAT

Troubleshooting

A check says "crashed". The check hit an unexpected error. Unfold it to read the message, and send it with the file to the pipeline team. The other checks still run.

"Shot start / end" is always skipped. The connection to Libreflow / Kitsu (providers.get_shot_frame_range) is not set up yet.

The character checks are skipped. Either no character reference is set (see Character reference), or the character name is unknown: type it in the Asset field, or name the file chr_<name>_mod.blend. Body vertex groups stays skipped until production lists the required groups (CHAR_BODY_VERTEX_GROUPS).

Rename: the preview shows nothing. Nothing is selected, the selection is linked from a library, or (in Materials mode) the selected objects have no local material.

Shot Viewer: a rig is not in the list. Only armatures in the scene's view layer are listed. A collection instance that has not been overridden does not expose its armature: make a library override first.

Shot Viewer: a shot is missing from the list. Only markers bound to a camera are shots. Select the marker, select its camera, and press Ctrl+B in the Timeline.

Shot Viewer: playback only plays one shot. Loop Shot is on. Untick it to play the whole sequence.


For developers

Layout

Path Content
__init__.py Registration
config.py Production values and the JSON override loader
providers.py Hooks to production tracking (Libreflow / Kitsu)
core/ Sanity check framework: Check, Issue, contexts, runner
checks/ The checks, one folder per family
ui/ Sanity Check operators, settings and every panel
rename.py Rename tool (logic, settings, operator)
shot_viewer.py Shot Viewer (logic, settings, operators)
tools_ops.py Libreflow tools (Get Oid)

Adding a check

Subclass Check in any module under checks/. A class that defines its own id is registered automatically:

from ...core import Check, Issue, contexts


class NoSuzanne(Check):
    id = "no_suzanne"
    label = "No Suzanne"
    description = "Monkeys are not allowed in production files."
    category = "Objects"
    contexts = contexts.ASSET

    def run(self, ctx):
        for ob in ctx.objects("MESH"):
            if "Suzanne" in ob.name:
                yield Issue.for_id(f"{ob.name} looks like a monkey", ob)

    # Optional: makes the wrench button appear.
    def fix(self, ctx, issues):
        ...
  • run yields Issues. No issue means the check passed.
  • Raise SkipCheck("reason") when the check cannot be evaluated.
  • fix may return messages describing what it could not fix.
  • Read config values at run time (config.FPS), never at import time, so that overrides apply.