asset_library/collection/create_collection_library.py

163 lines
5.2 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))