asset_library/collection/create_collection_library.py
2026-01-07 16:05:47 +01:00

183 lines
5.4 KiB
Python

import argparse
import sys
import os
import json
import uuid
import subprocess
import bpy
from pathlib import Path
from asset_library.common.functions import create_catalog_file
from asset_library.common.file_utils import get_last_files
from asset_library.constants import ASSETLIB_FILENAME
"""
### Create asset collection
## create_collection_library: generate all category blend from json
## if source_directory is set, call create_collection_json
## # create_collection_json:
## # scan marked blend, create json and call create_catalog_file
## # create_catalog_file
## # create catalog file from json file
### Json 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 create_collection_json(path, source_directory):
"""Create a Json from every marked collection in blends
contained in folderpath (respect hierachy)
"""
json_path = Path(path) / ASSETLIB_FILENAME
# scan all last version of the assets ?
# get last version files ?
# or open all blends and look only for marked collection ? (if versionned, get still get only last)
# get all blend in dir and subdirs (only last when versionned _v???)
blends = get_last_files(
source_directory, pattern=r"(_v\d{3})?\.blend$", only_matching=True
)
root_path = Path(source_directory).as_posix().rstrip("/") + "/"
print("root_path: ", root_path)
# open and check data block marked as asset
category_datas = []
for i, blend in enumerate(blends):
fp = Path(blend)
print(f"{i+1}/{len(blends)}")
## What is considered a grouping category ? top level folders ? parents[1] ?
## Remove root path and extension
## top level folder ('chars'), problem if blends at root
category = fp.as_posix().replace(root_path, "").split("/")[0]
## full blend path (chars/perso/perso)
# category = fp.as_posix().replace(root_path, '').rsplit('.', 1)[0]
print(category)
with bpy.data.libraries.load(blend, link=True, assets_only=True) as (
data_from,
data_to,
):
## just listing
col_name_list = [c for c in data_from.collections]
if not col_name_list:
continue
col_list = next(
(c["children"] for c in category_datas if c["name"] == category), None
)
if col_list is None:
col_list = []
category_data = {
"name": category,
"id": str(uuid.uuid4()),
"children": col_list,
}
category_datas.append(category_data)
blend_source_path = blend.as_posix()
if project_root := os.environ.get("PROJECT_ROOT"):
blend_source_path = blend_source_path.replace(project_root, "$PROJECT_ROOT")
for name in col_name_list:
data = {
"filepath": blend,
"name": name,
# 'tags' : [],
"metadata": {"filepath": blend_source_path},
}
col_list.append(data)
json_path.write_text(json.dumps(category_datas, indent="\t"))
## create text catalog from json (keep_existing_category ?)
create_catalog_file(json_path, keep_existing_category=True)
def create_collection_library(path, source_directory=None):
"""
path: store collection library (json and blends database)
source_directory: if a source is set, rebuild json and library
"""
if source_directory:
if not Path(source_directory).exists():
print(f"Source directory not exists: {source_directory}")
return
## scan source and build json in assetlib dir root
create_collection_json(path, source_directory)
json_path = Path(path) / ASSETLIB_FILENAME
if not json_path.exists():
print(f"No json found at: {json_path}")
return
file_datas = json.loads(json_path.read())
## For each category in json, execute build_assets_blend script
script = Path(__file__).parent / "build_collection_blends.py"
# empty_blend = Path(__file__).parent / 'empty_scene.blend'
# for category, asset_datas in file_datas.items():
for category_data in file_datas:
## add an empty blend as second arg
cmd = [
bpy.app.binary_path,
"--python",
str(script),
"--",
"--path",
path,
"--category",
category_data["name"],
]
print("cmd: ", cmd)
subprocess.call(cmd)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Create Collection Library",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"--path"
) # trouve/créer le json assetlib.json en sous-dossier de libdir
if "--" in sys.argv:
index = sys.argv.index("--")
sys.argv = [sys.argv[index - 1], *sys.argv[index + 1 :]]
args = parser.parse_args()
create_collection_library(**vars(args))