Files
wtd-libreflow-addon/CLAUDE.md
T
NDemaerschalkandClaude Opus 5.5 fbc7ac18e4 Scene Manager: Load Publish and numbered instances
Load Publish (Loaded panel) searches every asset of the project, then
loads any of its published .blend files at any version, cast in the shot
or not. The file the casting would load and the latest version on this
site are preselected; a version not on this site is requested instead.
Built on the existing wtd_list_assets / wtd_get_asset_files /
wtd_get_revisions commands.

New instances are numbered (COL_bob_01, tree_01...), counting on from the
highest number in the file (SCENE_MANAGER_INSTANCE_NAME).

README: Pick Shot only lists shots that exist in Libreflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:47:05 +01:00

7.3 KiB

Melvile Tools: notes for Claude

Blender add-on (Blender 5.2) for the Melvile pipeline at Walking The Dog: Sanity Check, Rename, Shot Manager and Scene Manager panels in the 3D View sidebar (WTD tab). README.md is the user guide: keep it up to date with every user-visible change.

Layout and conventions

  • config.py: every production value (prefixes, formats, patterns, modes). Values are read at run time (config.X, never copied at import) because a studio JSON file can override them (add-on preferences "Config Override", or WTD_SANITY_CONFIG). New tunable values go here, with a comment, and in the README's Configuration table.
  • ui/panel.py: all panels. Operators live with their tool (rename.py, shot_viewer.py, scene_manager/, ui/operators.py for the Sanity Check).
  • checks/: sanity checks, auto-registered (see README > For developers).
  • __init__.py deletes cached submodules on reload, so Reload Scripts picks up every file.
  • Versions: blender_manifest.toml and bl_info in __init__.py (keep both in sync).
  • Style: match the surrounding code; short docstrings, few comments, no heavy abstractions.

Working with the user

  • Commits: when asked, create a branch from master, commit there (end with the Co-Authored-By line), and give the user the merge / push / branch-delete commands: they run them themselves. Only commit straight on master when told to.
  • Real Blender API facts beat memory: probe in headless Blender before relying on an API.

Testing

Blender binary: macOS /Applications/Blender.app/Contents/MacOS/Blender, Windows blender.exe from the install folder. Import the add-on in tests by putting the folder that contains this repo on sys.path and importing the repo folder name (see dev/test_scene_manager.py).

  • Headless: blender -b --factory-startup --python-exit-code 1 --python <script> -- <args>. Timers do not run in background mode: pump background jobs by hand (scene_manager.ipc._poll()).
  • UI: run Blender with a window (--factory-startup <file.blend> --python <script>, a .blend argument avoids the splash), drive it with bpy.app.timers, take screenshots with bpy.ops.screen.screenshot_area, quit with bpy.ops.wm.quit_blender(). A sidebar tab (region.active_panel_category) can only be set once the region has been drawn.
  • Scene Manager without Libreflow (dev/):
    1. blender -b --factory-startup --python dev/make_test_assets.py -- <workdir>
    2. python dev/fake_libreflow.py <workdir> (keep running; restart for a clean state)
    3. blender -b --factory-startup --python-exit-code 1 --python dev/test_scene_manager.py -- <workdir> (71 checks, "All checks passed"). /_test/publish and /_test/download simulate a new publish and a requested revision reaching this site. The fake server follows the real wtdcmds replies; check them against the real Libreflow when one is available.

External pieces

  • Libreflow wtdcmds extension (commands used by the Scene Manager), on the share: WG/_Dev/GIT/ndemaerschalk/_MELVILE/libreflow_dev_utils/dev/src/wtdcmds/ (src/libreflow/extensions/wtdcmds/wtd_cmds.py, BLENDER_ADDON_BRIEF.md). Server address/token: ~/.kabaret/ipc/server.json (config LIBREFLOW_SERVER_FILE).
  • Add Camera Rigs extension: bpy.ops.object.build_camera_rig(mode=...) builds the Shot Manager cameras. It finds its rigs by the rig_id custom property, not by name.
  • tools_ops.py "Get Oid" uses the separate kabaret Blender client (bpy.ops.kabaret.cmds_call).

Design notes (found by testing)

  • Shot Manager: shots are timeline markers bound to cameras, in one scene. Setting scene.frame_current does not switch the camera (only frame_set does): set scene.camera explicitly.
  • Scene Manager: tags live on bpy.types.Library only. Library overrides lose custom properties when they resync, so instances are traced back to their library (empty → instance_collection.library, override → override_library.reference.library).
  • library.reload() invalidates every Python reference to linked and override data: look IDs up again afterwards. In Blender 5.2 it also replaces the Library itself (renamed after its file, custom properties gone): library.update() finds it by path and restores the name and tags.
  • Removing a library leaves the libraries it linked indirectly (e.g. Blender's geometry_nodes_essentials.blend): remove_unused_libraries() drops the ones whose data is no longer used, never a managed library.
  • LODs are child collections of the asset collection (COL_{asset}_LOD{lod}, any name, ordered by SCENE_MANAGER_LODS, then numbers, then names; the first is the default). Overrides switch by hide_viewport/hide_render on the LOD override collections: Blender stores them as override properties (kept through save, reload and resync) and hidden LODs are not evaluated. Collection instances instance the LOD collection itself. A second override's collections are renamed (.001): match LODs on override_library.reference.name.
  • "Shot Manager" is the user-facing name of what the code calls shot_viewer (module, operators, SHOT_VIEWER_* config keys kept for existing override files).
  • Background requests (scene_manager.ipc.run) hand results back through a timer; in callbacks, find scenes by name (bpy.context.scene is not reliable in timers).

Real Libreflow (first run, 2026-10-27)

  • Kitsu asset types: main_character, secondary_character, tertiary_character, main_props, secondary_props, set_props, vehicles, bg_location, bg_set, skies, setdress_bank. The fake server uses the same names.
  • Paths come back as Windows paths with backslashes; comment can be null.
  • Set dressing publishes (setdress_low) hold a whole layout scene: the set is the environments collection, next to lights, cameras, characters, _unused.
  • Tested live: connection, context, casting, load (instance and override), version switch and update, remove, assetize errors, one request (car_paul modeling.blend v001 → Requested). Not tested: an actual assetize publish (it writes to production). New wtdcmds commands need every Libreflow session restarted (a running one keeps the old code and answers 404).
  • Load Publish (2026-10-28) uses only existing commands (wtd_list_assets, wtd_get_asset_files, wtd_get_revisions): 309 assets in ~0.1 s, live-tested on car_paul (loaded twice: car_paul_01, car_paul_02).
  • /melvile/films/melvile has no sequences or shots in Libreflow yet; melvile_test has 9.
  • Deployed Libreflow (Overseer launcher): wtdcmds must be an "extension" entry, so the launcher adds libreflow.extensions.wtdcmds:install_extensions to KABARET_FLOW_EXT_INSTALLERS; the package name must stay libreflow.extensions.wtdcmds. The launcher only rebuilds its env when the project config changes: "Force update".

Open points

  • Override vs instance per asset type (SCENE_MANAGER_LINK_MODES), and the file patterns of sets (setdress_low seen on one asset only): confirm with production.
  • The server picks the first file matching a pattern even when it is not on this site, while another matching file is (e.g. car_paul: modeling/modeling.blend v001 not available, modeling/tes_modeling.blend v002 available).
  • Values marked TODO in config.py wait for production specs.