Files
wtd-libreflow-addon/README.md
T
NDemaerschalkandClaude Opus 5.5 9ee7710479 Scene Manager: fixes from the first run against a real Libreflow
- Update / version switch: Blender 5.2 replaces the library on reload
  (renamed after its file, custom properties gone); find it by path and
  restore its name and tags.
- Remove the libraries an asset linked indirectly when it is removed or
  fails to load (remove_unused_libraries), never a managed one.
- Config: real Kitsu asset types for link modes and Shot Viewer groups,
  setdress_low files for bg_location, "environments" collection fallback.
- Dev fake server and test use the real asset types; rock links a node
  group from the essentials to cover the indirect library cleanup.
- README and CLAUDE.md updated with the live findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:30:46 +01:00

519 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
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.
# Melvile Tools
Blender add-on for the Melvile pipeline (Walking The Dog). It brings together:
- **[Sanity Check](#sanity-check)**: checks a file against the production specs and fixes what can be fixed.
- **[Rename](#rename)**: batch renames objects and materials to the naming convention, with consistent numbering.
- **[Shot Viewer](#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.
- **[Scene Manager](#scene-manager)**: loads the assets cast in a shot from Libreflow, keeps them up to date, and publishes scene collections as new assets.
- **[Get Oid](#get-oid-for-open-scene)**: 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](#configuration).
---
## Contents
- [Installation](#installation)
- [Where to find the tools](#where-to-find-the-tools)
- [Sanity Check](#sanity-check)
- [Tools panel](#tools-panel)
- [Rename](#rename)
- [Shot Viewer](#shot-viewer)
- [Scene Manager](#scene-manager)
- [Configuration](#configuration)
- [Troubleshooting](#troubleshooting)
- [For developers](#for-developers)
---
## Installation
Tested on **Blender 5.2**.
The Shot Viewer builds its cameras with the **Add Camera Rigs** extension (*Edit > Preferences > Get Extensions*, search "Add Camera Rigs"). Install and enable it next to Melvile Tools.
The Scene Manager talks to a **running Libreflow** with the `wtdcmds` extension, on the same machine.
**As an extension (artists):** build the package, then in Blender go to *Edit > Preferences > Get Extensions > Install from Disk…* and pick the `.zip`.
```bash
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](#character-reference)). Falls back to the `WTD_CHAR_REFERENCE` environment variable. |
| **Config Override** | JSON file overriding values of `config.py` (see [Configuration](#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 |
| **Scene Manager** (Casting, Loaded, Assetize) | 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](#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](#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: builds a camera rig with the **Add Camera Rigs** add-on. The camera is named `CAM_<sequence>_<shot>` (shown in the dialog) and its rig `RIG_<sequence>_<shot>`. Off: pick an existing camera of the scene. |
| **3D Camera** | On: a 3D **crane** rig. Off: a **2D** camera rig. |
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.
The rig is built at the **3D cursor**, in the active collection: place the cursor and pick the collection first if you have a camera collection. The add-on keeps the rig's bone shapes in a hidden **Widgets** collection. If the add-on is not enabled, the dialog says so and no shot is added.
### 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 loaded by the [Scene Manager](#scene-manager) is grouped by its Libreflow asset type (`main_character`, `secondary_character`, `tertiary_character` → Characters; `main_props`, `secondary_props`, `vehicles` → Props; see `SHOT_VIEWER_ASSET_TYPE_GROUPS`). Otherwise, 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](#configuration)). Hidden rigs cannot be selected. Camera rigs (armatures carrying a camera) are not listed.
---
## Scene Manager
Manages the assets of a shot by talking to the running Libreflow: it reads the shot's casting (from Kitsu), links the published files of the cast assets, flags the ones that are out of date, and publishes local collections as new assets.
Everything goes through Libreflow: Blender never touches Kitsu or the Libreflow database. Requests run in the background, so Blender stays usable while Libreflow answers. What is in progress shows at the bottom of the main panel, with the last result (or error) under it.
### Connecting
Start Libreflow, then open *WTD tab > **Scene Manager***. Blender connects on its own when it starts and when a file is opened. Click the refresh icon on the first line to connect again, for example after starting Libreflow.
The first line shows the Libreflow session, the user and the site. When several Libreflow sessions are open, they are listed: click the one to work with.
### The shot (context)
The field under the connection is the **context**: the Libreflow oid of the shot this file belongs to, like `/melvile/films/f01/sequences/s010/shots/p010`. It is saved in the file and does not change when you browse in Libreflow.
- **Libreflow Oid**: takes the oid shown in the Libreflow window.
- **Pick Shot**: search the shots of the project.
A valid shot is confirmed under the field (`shot: f01 / s010 / p010`). The casting and the versions are then read on their own.
### Casting
Lists the assets cast in the shot, with how many instances are loaded out of how many are cast (`2/2`):
| Icon | Meaning |
|---|---|
| ✔ | Loaded. |
| Import arrow | Not loaded (or fewer instances than cast): click it to load this asset only. |
| ⚠ red | Cannot be loaded, with the reason from Libreflow: not found in the flow, no published file, or nothing available on this site yet. |
- **Load Missing** links every cast asset that is not loaded yet, and adds the missing instances. Running it again only adds what is missing.
- **Refresh** reads the casting and the versions again.
- **Loaded, no longer cast** lists assets loaded earlier that the shot's casting no longer contains.
**What gets loaded:**
- **File:** the latest publish **available on this site** of the asset's first file matching `rigging/*.blend`, then `modeling/*.blend` (sets, `bg_location`: `setdress_low/*.blend`).
- **Collection:** from that file, `COL_<asset>`, else `<asset>`, else `environments` (set dressing files), else the file's only top-level collection.
- **Characters, props and vehicles** (`*_character`, `main_props`, `secondary_props`, `vehicles`) become **library overrides**, so animators can pose them. Other types, like sets and set props, become **collection instances**.
- **Where they go:** each asset type gets its own collection, `COL_main_character`, `COL_main_props`, `COL_bg_location`…
All of these can be changed in the [Configuration](#configuration).
### Loaded
Lists everything the Scene Manager loaded, one line per asset, with its version:
- The version is **red** when it is not the latest publish. The line under it says either "v004 available" (click the update icon), or "v004 published, not available on this site yet" (wait for the download).
- **Arrow**: shows the asset's instances, each with a button to select its objects and one to remove it.
- **Menu icon**: pick another published version, for example to roll back. Versions not on this site are marked and cannot be picked.
- **✕**: removes the asset entirely: all its instances and the link to its file.
- **Update All** / **Update Selected**: switch all the loaded assets (or the ones of the selected objects) to their latest available publish.
- **Remove Selected**: removes the instances of the selected objects.
- The magnifier re-checks the versions.
Updating swaps the linked file and reloads it. Overrides keep their posing and animation. **Ctrl+Z** undoes removing and updating.
### Assetize
Publishes a collection of the scene to Libreflow as its own `.blend`: a new asset, or a new version of an existing one.
Click **Assetize Collection...** (in the *Assetize* sub-panel):
| Setting | Use |
|---|---|
| **Collection** | Local collections only. Collections holding loaded assets are not offered. The active collection of the Outliner is picked by default. |
| **Asset Type** | The Libreflow asset type (props, sets...). |
| **Asset Name** | Letters, digits and underscores. Taken from the collection name, without its prefix (`COL_street_lamp` → `street_lamp`). The dialog says whether this makes a **new asset** or a **new version** of an existing one. |
| **Asset Library** | Optional: publish under that asset library. |
| **Task** | The asset task to publish in (default `modeling`). If it does not exist, the error lists the asset's tasks. |
| **File Name** | Optional, defaults to the asset name. |
| **Comment** | Saved with the revision. |
| **Upload** | Also sends the revision to the exchange site. |
| **Replace with the Publish** | On by default: once published, the local collection is replaced by a link to the published file, so the Scene Manager manages it like any other asset. The local collection stays in the file, unlinked, renamed `<name>_local`. |
---
---
## 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.
```json
{
"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`. `SHOT_CAMERA_RIG_NAME_FORMAT` names the rig the same way, with `{prefix}` = `RIG_`. `SHOT_CAMERA_RIG_MODES` picks the Add Camera Rigs mode for 3D and 2D cameras (`CRANE` and `2D`; `DOLLY` is also available).
### 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_VIEWER_ASSET_TYPE_GROUPS`, `SHOT_NAME_FORMAT`, `SHOT_NUMBER_STEP`, `SHOT_FRAME_START`, `SHOT_DEFAULT_DURATION`, `SEQUENCE_NAME_FORMAT`, `SHOT_CAMERA_NAME_FORMAT`, `SHOT_CAMERA_RIG_NAME_FORMAT`, `SHOT_CAMERA_RIG_MODES` |
| Scene Manager | `LIBREFLOW_SERVER_FILE`, `LIBREFLOW_TIMEOUT`, `SCENE_MANAGER_FILE_PATTERNS`, `SCENE_MANAGER_COLLECTION_NAMES`, `SCENE_MANAGER_LINK_MODES`, `SCENE_MANAGER_TYPE_COLLECTION`, `SCENE_MANAGER_ASSETIZE_TASK` |
---
## 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](#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.
**Scene Manager: "Libreflow is not running".**
Start Libreflow (with the `wtdcmds` extension), then click the refresh icon of the Scene Manager. Its IPC server stops 30 seconds after the last Libreflow session closes.
**Scene Manager: an asset cannot be loaded.**
Its red line says why. "No file matching..." means none of its files matches `SCENE_MANAGER_FILE_PATTERNS`. "No collection named..." means the file has none of `COL_<asset>`, `<asset>` or `environments`, and several top-level collections: rename the published collection, or add its name to `SCENE_MANAGER_COLLECTION_NAMES`.
**Scene Manager: the version stays red after Update.**
The newer version is published but not downloaded on this site yet. Wait for the sync, then update again.
**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) |
| `scene_manager/` | Scene Manager: `ipc.py` (Libreflow client and background jobs), `library.py` (linking, overrides, updates), `operators.py` |
### Adding a check
Subclass `Check` in any module under `checks/`. A class that defines its own `id` is registered automatically:
```python
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 `Issue`s. 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.