import bpy from ... import config from ...core import Check, Issue, Severity, contexts, is_local class CollectionStructureCheck(Check): """Placeholder until the production hierarchy is defined: see REQUIRED_COLLECTIONS.""" id = "collection_structure" label = "Collection structure" description = ( "No object directly in the Scene Collection, no empty collections, " "and the required collections (config REQUIRED_COLLECTIONS) exist." ) category = "Structure" contexts = contexts.ASSET fix_description = "Remove empty collections" def run(self, ctx): scene = ctx.scene for ob in scene.collection.objects: yield Issue.for_id(f"'{ob.name}' is directly in the Scene Collection", ob) for name in config.REQUIRED_COLLECTIONS: if "{asset}" in name: if not ctx.asset_name: yield Issue(f"Cannot resolve required collection '{name}': unknown asset name") continue name = name.format(asset=ctx.asset_name) if name not in bpy.data.collections: yield Issue(f"Required collection '{name}' is missing") for collection in scene.collection.children_recursive: if is_local(collection) and not collection.all_objects and not collection.children: yield Issue.for_id( f"Collection '{collection.name}' is empty", collection, severity=Severity.WARNING, data={"empty": True}, ) def fix(self, ctx, issues): for issue in issues: if issue.data.get("empty"): collection = issue.get_id() if collection is not None: bpy.data.collections.remove(collection) unfixed = [i for i in issues if not i.data.get("empty")] return [f"{len(unfixed)} issue(s) must be fixed by hand"] if unfixed else []