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:
1 parent
017bdfc2fd
commit
9ee7710479
7 files changed
+109
-35
No files matched your search
@@ -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)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
Reference in new issue
Block a user