import argparse import bpy import sys import json from pathlib import Path from time import time, sleep from itertools import groupby from asset_library.common.bl_utils import load_datablocks, col_as_asset from asset_library.constants import ASSETLIB_FILENAME """ blender_assets.libs.json data Structure [ { 'name': 'chars/main', 'id': '013562-56315-4563156-123', 'children': [ { 'filepath' : '/z/...', 'name' : 'collection name', 'tags' : ['variation', 'machin', 'chose'], 'metadata' : {'filepath': '$PROJECT/...', 'version' : 'mushable'} }, { 'filepath' : '/z/...', }, ], }, ] """ def build_collection_blends(path, categories=None, clean=True): t0 = time() scn = bpy.context.scene scn.render.resolution_x = scn.render.resolution_y = 1000 json_path = Path(path) / ASSETLIB_FILENAME if not json_path.exists(): return # _col_datas = json.loads(json_path.read())[category] category_datas = json.loads(json_path.read_text()) for category_data in category_datas: if categories and category_data["name"] not in categories: continue bpy.ops.wm.read_homefile(use_empty=True) # category_data = next(c for c in category_datas if c['name'] == category) # _col_datas = category_data['children'] cat_name = category_data["name"] build_path = Path(path) / cat_name / f"{cat_name}.blend" ## re-iterate in grouped filepath col_datas = sorted(category_data["children"], key=lambda x: x["filepath"]) for filepath, col_data_groups in groupby( col_datas, key=lambda x: x["filepath"] ): # f = Path(f) if not Path(filepath).exists(): print(f"Not exists: {filepath}") continue col_data_groups = list(col_data_groups) col_names = [a["name"] for a in col_data_groups] linked_cols = load_datablocks( filepath, col_names, link=True, type="collections" ) for i, col in enumerate(linked_cols): # iterate in linked collection and associated data if not col: continue asset_data = col_data_groups[i] ## asset_data -> {'filepath': str, 'tags': list, 'metadata': dict} ## Directly link as collection inside a marked collection with same name marked_col = col_as_asset(col, verbose=True) marked_col.asset_data.description = asset_data.get("description", "") marked_col.asset_data.catalog_id = category_data["id"] # assign catalog for k, v in asset_data.get("metadata", {}).items(): marked_col.asset_data[k] = v ## exclude collections and generate preview bpy.ops.ed.lib_id_generate_preview({"id": marked_col}) # preview gen vcol = bpy.context.view_layer.layer_collection.children[marked_col.name] vcol.exclude = True sleep(1.0) ## clear all objects (can be very long with a lot of objects...): if clean: print("Removing links...") for lib in reversed(bpy.data.libraries): bpy.data.libraries.remove(lib) # Créer les dossiers intermediaires build_path.parent.mkdir(parents=True, exist_ok=True) print("Saving to", build_path) bpy.ops.wm.save_as_mainfile(filepath=str(build_path), compress=False) print("build time:", f"{time() - t0:.1f}s") bpy.ops.wm.quit_blender() if __name__ == "__main__": parser = argparse.ArgumentParser( description="build_collection_blends", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument( "-path" ) # Trouve/créer le json assetlib.json en sous-dossier de libdir parser.add_argument( "--category" ) # Lit la category dans le json et a link tout dans le blend if "--" in sys.argv: index = sys.argv.index("--") sys.argv = [sys.argv[index - 1], *sys.argv[index + 1 :]] args = parser.parse_args() build_collection_blends(**vars(args))