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>
This commit is contained in:
NDemaerschalkandClaude Opus 5.5 committed 2026-10-27 11:30:46 +01:00
1 parent 017bdfc2fd
commit 9ee7710479
7 files changed
+109 -35

No files matched your search

+31 -2
View File
@@ -135,6 +135,7 @@ def link_asset(asset, revision, context_oid):
f"{len(roots)} top-level collections in the file ({', '.join(c.name for c in roots)})"
)
bpy.data.libraries.remove(library)
remove_unused_libraries()
raise LoadError(message)
chosen = roots[0].name
@@ -177,14 +178,25 @@ def update(library_name, revision):
"""Point a library to another revision of its file and reload it."""
library = bpy.data.libraries[library_name]
path = _revision_path(revision, library.get("wtd_asset_name", library_name))
tags = dict(library)
library.filepath = path
library.reload()
# The reload replaces the linked data: look the library up again.
library = bpy.data.libraries[library_name]
# The reload replaces the library (named after its file, no custom properties):
# find it by its path, then give it back its name and tags.
library = next((lib for lib in bpy.data.libraries if _same_path(lib.filepath, path)), None)
if library is None:
raise LoadError(f"{library_name}: {os.path.basename(path)} could not be reloaded")
library.name = library_name
for key, value in tags.items():
library[key] = value
library["wtd_revision"] = revision["name"]
return library
def _same_path(a, b):
return os.path.normcase(os.path.normpath(bpy.path.abspath(a))) == os.path.normcase(os.path.normpath(b))
def remove_instance(instance):
if isinstance(instance, bpy.types.Object):
bpy.data.objects.remove(instance)
@@ -204,6 +216,23 @@ def remove_library(library):
for instance in instances(library):
remove_instance(instance)
bpy.data.libraries.remove(library)
remove_unused_libraries()
def remove_unused_libraries():
"""Remove the libraries none of whose data is used any more, e.g. the ones a removed
asset linked indirectly (node group assets...). Managed libraries are kept."""
while True:
used = {
id.library.name
for id in bpy.data.user_map()
if id.library is not None and (id.users or id.use_fake_user)
}
unused = [lib for lib in bpy.data.libraries if lib.name not in used and not lib.get(ASSET_OID)]
if not unused:
return
for lib in unused:
bpy.data.libraries.remove(lib)
# --------------------------------------------------------------------------- #