2023-01-17 18:05:22 +01:00
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
Plugin for making an asset library of all blender file found in a folder
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
2024-07-04 11:53:58 +02:00
|
|
|
|
from asset_library.plugins.scan_folder import ScanFolder
|
|
|
|
|
from asset_library.core.bl_utils import load_datablocks
|
|
|
|
|
from asset_library.core.template import Template
|
2023-01-17 18:05:22 +01:00
|
|
|
|
|
|
|
|
|
import bpy
|
|
|
|
|
from bpy.props import (StringProperty, IntProperty, BoolProperty)
|
|
|
|
|
import re
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from itertools import groupby
|
|
|
|
|
import uuid
|
|
|
|
|
import os
|
|
|
|
|
import shutil
|
|
|
|
|
import json
|
|
|
|
|
import time
|
|
|
|
|
from pprint import pprint
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Conform(ScanFolder):
|
|
|
|
|
|
|
|
|
|
name = "Conform"
|
|
|
|
|
source_directory : StringProperty(subtype='DIR_PATH')
|
|
|
|
|
|
|
|
|
|
target_template_file : StringProperty()
|
|
|
|
|
target_template_info : StringProperty()
|
|
|
|
|
target_template_image : StringProperty()
|
|
|
|
|
target_template_video : StringProperty()
|
|
|
|
|
|
|
|
|
|
def draw_prefs(self, layout):
|
|
|
|
|
layout.prop(self, "source_directory", text="Source : Directory")
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(self, "source_template_file", icon='COPY_ID', text='Template file')
|
|
|
|
|
col.prop(self, "source_template_image", icon='COPY_ID', text='Template image')
|
|
|
|
|
col.prop(self, "source_template_video", icon='COPY_ID', text='Template video')
|
|
|
|
|
col.prop(self, "source_template_info", icon='COPY_ID', text='Template info')
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(self, "target_template_file", icon='COPY_ID', text='Target : Template file')
|
|
|
|
|
col.prop(self, "target_template_image", icon='COPY_ID', text='Template image')
|
|
|
|
|
col.prop(self, "target_template_video", icon='COPY_ID', text='Template video')
|
|
|
|
|
col.prop(self, "target_template_info", icon='COPY_ID', text='Template info')
|
|
|
|
|
|
|
|
|
|
def get_asset_bundle_path(self, asset_data):
|
|
|
|
|
"""Template file are relative"""
|
|
|
|
|
|
|
|
|
|
src_directory = Path(self.source_directory).resolve()
|
|
|
|
|
src_template_file = Template(self.source_template_file)
|
|
|
|
|
|
|
|
|
|
asset_path = Path(asset_data['filepath']).as_posix()
|
|
|
|
|
asset_path = self.format_path(asset_path)
|
|
|
|
|
|
|
|
|
|
rel_path = asset_path.relative_to(src_directory).as_posix()
|
|
|
|
|
field_data = src_template_file.parse(rel_path)
|
|
|
|
|
#field_data = {f"catalog_{k}": v for k, v in field_data.items()}
|
|
|
|
|
|
|
|
|
|
# Change the int in the template by string to allow format
|
|
|
|
|
#target_template_file = re.sub(r'{(\d+)}', r'{cat\1}', self.target_template_file)
|
|
|
|
|
|
|
|
|
|
format_data = self.format_asset_data(asset_data)
|
|
|
|
|
#format_data['asset_name'] = format_data['asset_name'].lower().replace(' ', '_')
|
|
|
|
|
|
|
|
|
|
path = Template(self.target_template_file).format(format_data, **field_data).with_suffix('.blend')
|
|
|
|
|
path = Path(self.bundle_directory, path).resolve()
|
|
|
|
|
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
def set_asset_preview(self, asset, asset_data):
|
|
|
|
|
'''Load an externalize image as preview for an asset using the target template'''
|
|
|
|
|
|
|
|
|
|
image_template = self.target_template_image
|
|
|
|
|
if not image_template:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
asset_path = self.get_asset_bundle_path(asset_data)
|
|
|
|
|
image_path = self.find_path(image_template, asset_data, filepath=asset_path)
|
|
|
|
|
|
|
|
|
|
if image_path:
|
|
|
|
|
with bpy.context.temp_override(id=asset):
|
|
|
|
|
bpy.ops.ed.lib_id_load_custom_preview(
|
|
|
|
|
filepath=str(image_path)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
print(f'No image found for {image_template} on {asset.name}')
|
|
|
|
|
|
|
|
|
|
if asset.preview:
|
|
|
|
|
return asset.preview
|
|
|
|
|
|
2023-05-10 09:59:07 +02:00
|
|
|
|
def generate_previews(self, cache_diff):
|
2023-01-17 18:05:22 +01:00
|
|
|
|
|
|
|
|
|
print('Generate previews...')
|
|
|
|
|
|
2023-05-10 09:59:07 +02:00
|
|
|
|
# if cache in (None, ''):
|
|
|
|
|
# cache = self.fetch()
|
|
|
|
|
# elif isinstance(cache, (Path, str)):
|
|
|
|
|
# cache = self.read_cache(cache)
|
|
|
|
|
|
|
|
|
|
if isinstance(cache, (Path, str)):
|
|
|
|
|
cache_diff = LibraryCacheDiff(cache_diff)
|
|
|
|
|
|
2023-01-17 18:05:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#TODO Support all multiple data_type
|
|
|
|
|
for asset_info in cache:
|
|
|
|
|
|
|
|
|
|
if asset_info.get('type', self.data_type) == 'FILE':
|
|
|
|
|
self.generate_blend_preview(asset_info)
|
|
|
|
|
else:
|
|
|
|
|
self.generate_asset_preview(asset_info)
|
|
|
|
|
|
|
|
|
|
def generate_asset_preview(self, asset_info):
|
|
|
|
|
"""Only generate preview when conforming a library"""
|
|
|
|
|
|
|
|
|
|
#print('\ngenerate_preview', asset_info['filepath'])
|
|
|
|
|
|
|
|
|
|
scn = bpy.context.scene
|
|
|
|
|
vl = bpy.context.view_layer
|
|
|
|
|
#Creating the preview for collection, object or material
|
|
|
|
|
#camera = scn.camera
|
|
|
|
|
|
|
|
|
|
data_type = self.data_type #asset_info['data_type']
|
|
|
|
|
asset_path = self.format_path(asset_info['filepath'])
|
|
|
|
|
|
|
|
|
|
# Check if a source video exists and if so copying it in the new directory
|
|
|
|
|
if self.source_template_video and self.target_template_video:
|
|
|
|
|
for asset_data in asset_info['assets']:
|
|
|
|
|
asset_data = dict(asset_data, filepath=asset_path)
|
|
|
|
|
|
|
|
|
|
dst_asset_path = self.get_asset_bundle_path(asset_data)
|
|
|
|
|
dst_video_path = self.format_path(self.target_template_video, asset_data, filepath=dst_asset_path)
|
|
|
|
|
if dst_video_path.exists():
|
|
|
|
|
print(f'The dest video {dst_video_path} already exist')
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
src_video_path = self.find_path(self.source_template_video, asset_data)
|
|
|
|
|
if src_video_path:
|
|
|
|
|
print(f'Copy video from {src_video_path} to {dst_video_path}')
|
|
|
|
|
self.copy_file(src_video_path, dst_video_path)
|
|
|
|
|
|
|
|
|
|
# Check if asset as a preview image or need it to be generated
|
|
|
|
|
asset_data_names = {}
|
|
|
|
|
|
|
|
|
|
if self.target_template_image:
|
|
|
|
|
for asset_data in asset_info['assets']:
|
|
|
|
|
asset_data = dict(asset_data, filepath=asset_path)
|
|
|
|
|
name = asset_data['name']
|
|
|
|
|
dst_asset_path = self.get_asset_bundle_path(asset_data)
|
|
|
|
|
|
|
|
|
|
dst_image_path = self.format_path(self.target_template_image, asset_data, filepath=dst_asset_path)
|
|
|
|
|
if dst_image_path.exists():
|
|
|
|
|
print(f'The dest image {dst_image_path} already exist')
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Check if a source image exists and if so copying it in the new directory
|
|
|
|
|
if self.source_template_image:
|
|
|
|
|
src_image_path = self.find_path(self.source_template_image, asset_data)
|
|
|
|
|
|
|
|
|
|
if src_image_path:
|
|
|
|
|
if src_image_path.suffix == dst_image_path.suffix:
|
|
|
|
|
self.copy_file(src_image_path, dst_image_path)
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
print(src_image_path)
|
|
|
|
|
self.save_image(src_image_path, dst_image_path, remove=True)
|
|
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
#Store in a dict all asset_data that does not have preview
|
|
|
|
|
asset_data_names[name] = dict(asset_data, image_path=dst_image_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not asset_data_names:# No preview to generate
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print('Making Preview for', list(asset_data_names.keys()))
|
|
|
|
|
|
|
|
|
|
asset_names = list(asset_data_names.keys())
|
|
|
|
|
assets = self.load_datablocks(asset_path, names=asset_names, link=True, type=data_type)
|
|
|
|
|
|
|
|
|
|
for asset in assets:
|
|
|
|
|
if not asset:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
asset_data = asset_data_names[asset.name]
|
|
|
|
|
image_path = asset_data['image_path']
|
|
|
|
|
|
|
|
|
|
if asset.preview:
|
|
|
|
|
print(f'Writing asset preview to {image_path}')
|
|
|
|
|
self.write_preview(asset.preview, image_path)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if data_type == 'COLLECTION':
|
|
|
|
|
|
|
|
|
|
bpy.ops.object.collection_instance_add(name=asset.name)
|
|
|
|
|
|
|
|
|
|
bpy.ops.view3d.camera_to_view_selected()
|
|
|
|
|
instance = vl.objects.active
|
|
|
|
|
|
|
|
|
|
#scn.collection.children.link(asset)
|
|
|
|
|
|
|
|
|
|
scn.render.filepath = str(image_path)
|
|
|
|
|
|
|
|
|
|
print(f'Render asset {asset.name} to {image_path}')
|
|
|
|
|
bpy.ops.render.render(write_still=True)
|
|
|
|
|
|
|
|
|
|
#instance.user_clear()
|
|
|
|
|
asset.user_clear()
|
|
|
|
|
|
|
|
|
|
bpy.data.objects.remove(instance)
|
|
|
|
|
|
|
|
|
|
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|