finish make library conformation working

master
“christopheseux” 2022-12-30 23:36:09 +01:00
parent ab72a15a2c
commit 501cb460c8
19 changed files with 319 additions and 303 deletions

View File

@ -22,6 +22,8 @@ if 'bpy' in locals():
importlib.reload(rename_pose) importlib.reload(rename_pose)
#importlib.reload(render_preview) #importlib.reload(render_preview)
import bpy
def register(): def register():
operators.register() operators.register()
keymaps.register() keymaps.register()

View File

@ -72,11 +72,11 @@ from asset_library.action.functions import (
from asset_library.common.functions import ( from asset_library.common.functions import (
#get_actionlib_dir, #get_actionlib_dir,
get_asset_source, #get_asset_source,
#get_catalog_path, #get_catalog_path,
#read_catalog, #read_catalog,
#set_actionlib_dir, #set_actionlib_dir,
resync_lib, #resync_lib,
get_active_library, get_active_library,
get_active_catalog, get_active_catalog,
asset_warning_callback asset_warning_callback

BIN
action/preview.blend Normal file

Binary file not shown.

View File

@ -3,7 +3,7 @@
from asset_library.common.bl_utils import get_addon_prefs, load_datablocks from asset_library.common.bl_utils import get_addon_prefs, load_datablocks
from asset_library.common.file_utils import read_file, write_file from asset_library.common.file_utils import read_file, write_file
from asset_library.common.template import Template from asset_library.common.template import Template
from asset_library.constants import (PREVIEW_ASSETS_SCRIPT, MODULE_DIR) from asset_library.constants import (MODULE_DIR, RESOURCES_DIR)
from asset_library import (action, collection, file) from asset_library import (action, collection, file)
@ -36,48 +36,26 @@ class AssetLibraryAdapter(PropertyGroup):
for lib in prefs.libraries: for lib in prefs.libraries:
if lib.adapter == self: if lib.adapter == self:
return lib return lib
if lib.conform.adapter == self:
return lib
#@property
#def library_path(self):
# return self.library.library_path
@property @property
def is_conform(self): def bundle_directory(self):
prefs = self.addon_prefs return self.library.library_path
for lib in prefs.libraries:
if lib.adapter == self:
return False
if lib.conform.adapter == self:
return True
@property # @property
def target_directory(self): # def blend_depth(self):
if self.is_conform: # return self.library.blend_depth
return self.library.conform.directory
return self.library.bundle_directory # @property
# def template_image(self):
# return Template(self.library.template_image)
@property # @property
def blend_depth(self): # def template_video(self):
if self.is_conform: # return Template(self.library.template_video)
return self.library.conform.blend_depth
return self.library.blend_depth
@property
def template_image(self):
return Template(self.library.conform.template_image)
@property
def template_video(self):
return Template(self.library.conform.template_video)
@property
def template_description(self):
return Template(self.library.conform.template_description)
# @property
# def template_description(self):
# return Template(self.library.template_description)
@property @property
def data_type(self): def data_type(self):
@ -87,21 +65,18 @@ class AssetLibraryAdapter(PropertyGroup):
def data_types(self): def data_types(self):
return self.library.data_types return self.library.data_types
#@property
#def externalize_data(self):
# return self.library.externalize_data
#@property
#def catalog_path(self):
# return self.library.catalog_path
def get_catalog_path(self, directory=None): def get_catalog_path(self, directory=None):
directory = directory or self.target_directory directory = directory or self.bundle_directory
return Path(directory, 'blender_assets.cats.txt') return Path(directory, 'blender_assets.cats.txt')
@property @property
def cache_file(self): def cache_file(self):
return Path(self.target_directory) / f"blender_assets.{self.library.id}.json" return Path(self.bundle_directory) / f"blender_assets.{self.library.id}.json"
#return get_asset_datas_file(self.library_path)
@property
def tmp_cache_file(self):
return Path(bpy.app.tempdir) / f"blender_assets.{self.library.id}.json"
#return get_asset_datas_file(self.library_path) #return get_asset_datas_file(self.library_path)
@property @property
@ -149,22 +124,26 @@ class AssetLibraryAdapter(PropertyGroup):
src = Path(source) src = Path(source)
dst = Path(destination) dst = Path(destination)
if not source.exists(): if not src.exists():
print(f'Cannot copy file {source}: file not exist') print(f'Cannot copy file {src}: file not exist')
return return
dst.parent.mkdir(exist_ok=True, parents=True) dst.parent.mkdir(exist_ok=True, parents=True)
if src == dst: if src == dst:
print(f'Cannot copy file {source}: source and destination are the same') print(f'Cannot copy file {src}: source and destination are the same')
return return
print(f'Copy file from {source} to {destination}') print(f'Copy file from {src} to {dst}')
shutil.copy2(str(source), str(destination)) shutil.copy2(str(src), str(dst))
def load_datablocks(self, src, names=None, type='objects', link=True, expr=None): def load_datablocks(self, src, names=None, type='objects', link=True, expr=None, assets_only=False):
"""Link or append a datablock from a blendfile""" """Link or append a datablock from a blendfile"""
return load_datablocks(src, names=names, type=type, link=link, expr=expr)
if type.isupper():
type = f'{type.lower()}s'
return load_datablocks(src, names=names, type=type, link=link, expr=expr, assets_only=assets_only)
def get_asset_relative_path(self, name, catalog): def get_asset_relative_path(self, name, catalog):
'''Get a relative path for the asset''' '''Get a relative path for the asset'''
@ -220,7 +199,7 @@ class AssetLibraryAdapter(PropertyGroup):
template = Path(asset_path, template).as_posix() template = Path(asset_path, template).as_posix()
params = { params = {
'name': name, 'asset_name': name,
'asset_path': Path(asset_path), 'asset_path': Path(asset_path),
'catalog': catalog, 'catalog': catalog,
'catalog_name': catalog.replace('/', '_'), 'catalog_name': catalog.replace('/', '_'),
@ -230,13 +209,13 @@ class AssetLibraryAdapter(PropertyGroup):
def get_description_path(self, name, asset_path, catalog) -> Path: def get_description_path(self, name, asset_path, catalog) -> Path:
""""Get the path of the json or yaml describing all assets data in one file""" """"Get the path of the json or yaml describing all assets data in one file"""
return self.get_template_path(self.library.conform.template_description, name, asset_path, catalog) return self.get_template_path(self.library.template_description, name, asset_path, catalog)
def get_image_path(self, name, asset_path, catalog) -> Path: def get_image_path(self, name, asset_path, catalog) -> Path:
return self.get_template_path(self.library.conform.template_image, name, asset_path, catalog) return self.get_template_path(self.library.template_image, name, asset_path, catalog)
def get_video_path(self, name, asset_path, catalog) -> Path: def get_video_path(self, name, asset_path, catalog) -> Path:
return self.get_template_path(self.library.conform.template_video, name, asset_path, catalog) return self.get_template_path(self.library.template_video, name, asset_path, catalog)
''' '''
def get_path(self, type, name, asset_path, template=None) -> Path: def get_path(self, type, name, asset_path, template=None) -> Path:
@ -355,12 +334,13 @@ class AssetLibraryAdapter(PropertyGroup):
print(f'Catalog writen at: {catalog_path}') print(f'Catalog writen at: {catalog_path}')
catalog_path.write_text('\n'.join(lines), encoding="utf-8") catalog_path.write_text('\n'.join(lines), encoding="utf-8")
def read_cache(self): def read_cache(self, cache_path=None):
print(f'Read cache from {self.cache_file}') cache_path = cache_path or self.cache_file
return self.read_file(self.cache_file) print(f'Read cache from {cache_path}')
return self.read_file(cache_path)
def write_cache(self, asset_descriptions): def write_cache(self, asset_descriptions, cache_path=None):
cache_path = self.cache_file cache_path = cache_path or self.cache_file
print(f'cache file writen to {cache_path}') print(f'cache file writen to {cache_path}')
return write_file(cache_path, list(asset_descriptions)) return write_file(cache_path, list(asset_descriptions))
@ -408,7 +388,7 @@ class AssetLibraryAdapter(PropertyGroup):
catalog_parts = asset_data['catalog'].split('/') + [asset_data['name']] catalog_parts = asset_data['catalog'].split('/') + [asset_data['name']]
return catalog_parts[:self.blend_depth] return catalog_parts[:self.library.blend_depth]
#def transfert_preview(self, ) #def transfert_preview(self, )
@ -463,10 +443,44 @@ class AssetLibraryAdapter(PropertyGroup):
) )
) )
''' '''
def generate_preview(self, asset_description):
def generate_blend_preview(self, asset_description):
asset_name = asset_description['name']
catalog = asset_description['catalog']
asset_path = self.format_path(asset_description['filepath'])
dst_image_path = self.get_image_path(asset_name, asset_path, catalog)
if dst_image_path.exists():
return
# Check if a source image exists and if so copying it in the new directory
src_image_path = asset_description.get('image')
if src_image_path:
src_image_path = self.get_template_path(src_image_path, asset_name, asset_path, catalog)
if src_image_path and src_image_path.exists():
self.copy_file(src_image_path, dst_image_path)
return
print(f'Thumbnailing {asset_path} to {dst_image_path}')
blender_thumbnailer = Path(bpy.app.binary_path).parent / 'blender-thumbnailer'
dst_image_path.parent.mkdir(exist_ok=True, parents=True)
subprocess.call([blender_thumbnailer, str(asset_path), str(dst_image_path)])
success = dst_image_path.exists()
if not success:
empty_preview = RESOURCES_DIR / 'empty_preview.png'
self.copy_file(str(empty_preview), str(dst_image_path))
return success
def generate_asset_preview(self, asset_description):
"""Only generate preview when conforming a library""" """Only generate preview when conforming a library"""
print('\ngenerate_preview', asset_description) print('\ngenerate_preview', asset_description['filepath'])
scn = bpy.context.scene scn = bpy.context.scene
#Creating the preview for collection, object or material #Creating the preview for collection, object or material
@ -474,19 +488,28 @@ class AssetLibraryAdapter(PropertyGroup):
vl = bpy.context.view_layer vl = bpy.context.view_layer
data_type = self.data_type #asset_description['data_type'] data_type = self.data_type #asset_description['data_type']
asset_path = asset_description['filepath'] asset_path = self.format_path(asset_description['filepath'])
asset_data_names = {} asset_data_names = {}
for asset_data in asset_description['assets']: for asset_data in asset_description['assets']:
name = asset_data['name'] name = asset_data['name']
catalog = asset_data['catalog'] catalog = asset_data['catalog']
image_path = self.get_image_path(name, asset_path, catalog) dst_image_path = self.get_image_path(name, asset_path, catalog)
if image_path.exists(): if dst_image_path.exists():
continue continue
# Check if a source image exists and if so copying it in the new directory
src_image_path = asset_data.get('image')
if src_image_path:
src_image_path = self.get_template_path(src_image_path, name, asset_path, catalog)
if src_image_path and src_image_path.exists():
self.copy_file(src_image_path, dst_image_path)
return
#Store in a dict all asset_data that does not have preview #Store in a dict all asset_data that does not have preview
asset_data_names[name] = dict(asset_data, image_path=image_path) asset_data_names[name] = dict(asset_data, image_path=dst_image_path)
if not asset_data_names: if not asset_data_names:
# No preview to generate # No preview to generate
@ -512,8 +535,6 @@ class AssetLibraryAdapter(PropertyGroup):
scn.render.filepath = str(image_path) scn.render.filepath = str(image_path)
print(f'Render asset {asset.name} to {image_path}') print(f'Render asset {asset.name} to {image_path}')
bpy.ops.render.render(write_still=True) bpy.ops.render.render(write_still=True)
@ -522,25 +543,27 @@ class AssetLibraryAdapter(PropertyGroup):
bpy.data.objects.remove(instance) bpy.data.objects.remove(instance)
#bpy.ops.object.delete(use_global=False)
#scn.collection.children.unlink(asset)
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
def generate_previews(self, asset_descriptions=None): def generate_previews(self, cache=None):
print('Generate previews') print('Generate previews')
asset_descriptions = asset_descriptions or self.fetch() if cache in (None, ''):
cache = self.fetch()
elif isinstance(cache, (Path, str)):
cache = self.read_cache(cache)
#cache_diff.sort(key=lambda x :x['filepath']) #cache_diff.sort(key=lambda x :x['filepath'])
#blend_groups = groupby(cache_diff, key=lambda x :x['filepath']) #blend_groups = groupby(cache_diff, key=lambda x :x['filepath'])
#TODO Support all multiple data_type #TODO Support all multiple data_type
for asset_description in asset_descriptions: for asset_description in cache:
self.generate_preview(asset_description)
if asset_description['type'] == 'FILE':
self.generate_blend_preview(asset_description)
else:
self.generate_asset_preview(asset_description)
# filepath = asset_description['filepath'] # filepath = asset_description['filepath']
@ -561,7 +584,11 @@ class AssetLibraryAdapter(PropertyGroup):
asset_path = asset_data['filepath'] asset_path = asset_data['filepath']
catalog = asset_data['catalog'] catalog = asset_data['catalog']
image_path = self.get_image_path(name, asset_path, catalog) image_path = asset_data.get('image')
if self.library.template_image:
image_path = self.get_image_path(name, asset_path, catalog)
elif image_path:
image_path = self.get_template_path(image_path, name, asset_path, catalog)
if image_path and image_path.exists(): if image_path and image_path.exists():
with bpy.context.temp_override(id=asset): with bpy.context.temp_override(id=asset):
@ -663,9 +690,6 @@ class AssetLibraryAdapter(PropertyGroup):
print(f'{self.data_type} is not supported yet') print(f'{self.data_type} is not supported yet')
return return
target_dir = self.target_directory
catalog_data = self.read_catalog() #TODO remove unused catalog catalog_data = self.read_catalog() #TODO remove unused catalog
write_cache = False write_cache = False
@ -673,12 +697,15 @@ class AssetLibraryAdapter(PropertyGroup):
# Get list of all modifications # Get list of all modifications
asset_descriptions = self.fetch() asset_descriptions = self.fetch()
cache, cache_diff = self.diff(asset_descriptions) cache, cache_diff = self.diff(asset_descriptions)
# Only write complete cache at the end # Only write complete cache at the end
write_cache = True write_cache = True
self.generate_previews(asset_descriptions) #self.generate_previews(asset_descriptions)
self.write_cache(asset_descriptions, self.tmp_cache_file)
bpy.ops.assetlib.generate_previews(name=self.library.name, cache=str(self.tmp_cache_file))
#print() #print()
#print(cache) #print(cache)
@ -688,7 +715,7 @@ class AssetLibraryAdapter(PropertyGroup):
cache_diff = json.loads(Path(cache_diff).read_text(encoding='utf-8')) cache_diff = json.loads(Path(cache_diff).read_text(encoding='utf-8'))
if self.blend_depth == 0: if self.library.blend_depth == 0:
raise Exception('Blender depth must be 1 at min') raise Exception('Blender depth must be 1 at min')
#groups = [(cache_diff)] #groups = [(cache_diff)]
else: else:
@ -702,11 +729,14 @@ class AssetLibraryAdapter(PropertyGroup):
print('No assets found') print('No assets found')
return return
#data_types = self.data_types
#if self.data_types == 'FILE'
i = 0 i = 0
#assets_to_preview = [] #assets_to_preview = []
for sub_path, asset_datas in groups: for sub_path, asset_datas in groups:
blend_name = sub_path[-1].replace(' ', '_').lower() blend_name = sub_path[-1].replace(' ', '_').lower()
blend_path = Path(target_dir, *sub_path, blend_name).with_suffix('.blend') blend_path = Path(self.bundle_directory, *sub_path, blend_name).with_suffix('.blend')
if blend_path.exists(): if blend_path.exists():
print(f'Opening existing bundle blend: {blend_path}') print(f'Opening existing bundle blend: {blend_path}')
@ -768,7 +798,6 @@ class AssetLibraryAdapter(PropertyGroup):
print(f'Saving Blend to {blend_path}') print(f'Saving Blend to {blend_path}')
blend_path.parent.mkdir(exist_ok=True, parents=True) blend_path.parent.mkdir(exist_ok=True, parents=True)
bpy.ops.wm.save_as_mainfile(filepath=str(blend_path), compress=True) bpy.ops.wm.save_as_mainfile(filepath=str(blend_path), compress=True)
if write_cache: if write_cache:
@ -847,8 +876,8 @@ class AssetLibraryAdapter(PropertyGroup):
def format_path(self, template, **kargs): def format_path(self, template, **kargs):
params = dict( params = dict(
bundle_dir=Path(self.library.bundle_directory), bundle_dir=Path(self.bundle_directory),
conform_dir=Path(self.library.conform.directory), #conform_dir=Path(self.library.conform.directory),
**kargs, **kargs,
**self.to_dict(), **self.to_dict(),
) )

View File

@ -8,6 +8,7 @@ from asset_library.adapters.adapter import AssetLibraryAdapter
from asset_library.common.file_utils import copy_dir from asset_library.common.file_utils import copy_dir
from bpy.props import StringProperty from bpy.props import StringProperty
from os.path import expandvars from os.path import expandvars
import bpy
class CopyFolderLibrary(AssetLibraryAdapter): class CopyFolderLibrary(AssetLibraryAdapter):
@ -21,7 +22,7 @@ class CopyFolderLibrary(AssetLibraryAdapter):
def bundle(self, cache_diff=None): def bundle(self, cache_diff=None):
src = expandvars(self.source_directory) src = expandvars(self.source_directory)
dst = expandvars(self.target_directory) dst = expandvars(self.bundle_directory)
includes = [inc.strip() for inc in self.includes.split(',')] includes = [inc.strip() for inc in self.includes.split(',')]
excludes = [ex.strip() for ex in self.excludes.split(',')] excludes = [ex.strip() for ex in self.excludes.split(',')]
@ -32,3 +33,14 @@ class CopyFolderLibrary(AssetLibraryAdapter):
excludes=excludes, includes=includes excludes=excludes, includes=includes
) )
def filter_prop(self, prop):
if prop in ('template_description', 'template_video', 'template_image', 'blend_depth'):
return False
return True
# def draw_prop(self, layout, prop):
# if prop in ('template_description', 'template_video', 'template_image', 'blend_depth'):
# return
# super().draw_prop(layout)

View File

@ -28,6 +28,7 @@ class KitsuLibrary(AssetLibraryAdapter):
template_name : StringProperty() template_name : StringProperty()
template_file : StringProperty() template_file : StringProperty()
source_directory : StringProperty(subtype='DIR_PATH') source_directory : StringProperty(subtype='DIR_PATH')
#blend_depth: IntProperty(default=1)
url: StringProperty() url: StringProperty()
login: StringProperty() login: StringProperty()
@ -83,8 +84,8 @@ class KitsuLibrary(AssetLibraryAdapter):
description=data['description'], description=data['description'],
tags=[], tags=[],
type=self.data_type, type=self.data_type,
image=self.template_image.raw, image=self.library.template_image,
video=self.template_video.raw, video=self.library.template_video,
name=data['name']) name=data['name'])
] ]
) )
@ -96,16 +97,6 @@ class KitsuLibrary(AssetLibraryAdapter):
# return super().bundle(cache_diff=cache_diff) # return super().bundle(cache_diff=cache_diff)
def get_preview(self, asset_data):
name = asset_data['name']
preview = (f / template_image.format(name=name)).resolve()
if not preview.exists():
preview_blend_file(f, preview)
return preview
def fetch(self): def fetch(self):
"""Gather in a list all assets found in the folder""" """Gather in a list all assets found in the folder"""
@ -122,11 +113,11 @@ class KitsuLibrary(AssetLibraryAdapter):
entity_types_ids = {e['id']: e['name'] for e in entity_types} entity_types_ids = {e['id']: e['name'] for e in entity_types}
asset_descriptions = [] asset_descriptions = []
for asset_data in gazu.asset.all_assets_for_project(project)[:10]: for asset_data in gazu.asset.all_assets_for_project(project):
asset_data['entity_type_name'] = entity_types_ids[asset_data.pop('entity_type_id')] asset_data['entity_type_name'] = entity_types_ids[asset_data.pop('entity_type_id')]
asset_name = asset_data['name'] asset_name = asset_data['name']
asset_field_data = dict(name=asset_name, type=asset_data['entity_type_name'], source_directory=self.source_directory) asset_field_data = dict(asset_name=asset_name, type=asset_data['entity_type_name'], source_directory=self.source_directory)
try: try:
asset_field_data.update(template_name.parse(asset_name)) asset_field_data.update(template_name.parse(asset_name))
@ -140,6 +131,7 @@ class KitsuLibrary(AssetLibraryAdapter):
#print(asset_path) #print(asset_path)
# TODO group when multiple asset are store in the same blend
asset_descriptions.append(self.get_asset_description(asset_data, asset_path)) asset_descriptions.append(self.get_asset_description(asset_data, asset_path))
#asset = load_datablocks(asset_path, data_type='collections', names=asset_data['name'], link=True) #asset = load_datablocks(asset_path, data_type='collections', names=asset_data['name'], link=True)

View File

@ -23,8 +23,11 @@ class ScanFolderLibrary(AssetLibraryAdapter):
name = "Scan Folder" name = "Scan Folder"
source_directory : StringProperty(subtype='DIR_PATH') source_directory : StringProperty(subtype='DIR_PATH')
template : StringProperty() template_file : StringProperty()
blend_depth : IntProperty() template_image : StringProperty()
template_video : StringProperty()
template_description : StringProperty()
#blend_depth : IntProperty()
#externalize_preview : BoolProperty(default=True) #externalize_preview : BoolProperty(default=True)
#def draw_header(self, layout): #def draw_header(self, layout):
@ -38,6 +41,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
directory = directory or self.source_directory directory = directory or self.source_directory
return Path(directory, self.get_asset_relative_path(name, catalog)) return Path(directory, self.get_asset_relative_path(name, catalog))
'''
def get_asset_description(self, asset, catalog, modified): def get_asset_description(self, asset, catalog, modified):
asset_path = self.get_asset_relative_path(name=asset.name, catalog=catalog) asset_path = self.get_asset_relative_path(name=asset.name, catalog=catalog)
@ -61,6 +65,38 @@ class ScanFolderLibrary(AssetLibraryAdapter):
) )
return asset_description return asset_description
'''
def get_asset_description(self, data, asset_path):
asset_path = self.prop_rel_path(asset_path, 'source_directory')
if self.data_type == 'FILE':
return dict(
filepath=asset_path,
modified=data['modified'],
catalog=data['catalog'],
tags=[],
type=self.data_type,
image=self.template_image,
name=data['name']
)
return dict(
filepath=asset_path,
modified=data['modified'],
library_id=self.library.id,
assets=[dict(
catalog=asset_data['catalog'],
metadata=asset_data.get('metadata', {}),
description=asset_data.get('description'),
tags=asset_data.get('tags', []),
type=self.data_type,
image=self.template_image,
video=self.template_video,
name=asset_data['name']) for asset_data in data['assets']
]
)
def _find_blend_files(self): def _find_blend_files(self):
'''Get a sorted list of all blender files found matching the template''' '''Get a sorted list of all blender files found matching the template'''
@ -76,6 +112,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
return blend_files return blend_files
'''
def _group_key(self, asset_data): def _group_key(self, asset_data):
"""Group assets inside one blend""" """Group assets inside one blend"""
@ -238,17 +275,9 @@ class ScanFolderLibrary(AssetLibraryAdapter):
self.write_catalog(catalog_data) self.write_catalog(catalog_data)
bpy.ops.wm.quit_blender() bpy.ops.wm.quit_blender()
'''
def get_preview(self, asset_data): '''
name = asset_data['name']
preview = (f / template_image.format(name=name)).resolve()
if not preview.exists():
preview_blend_file(f, preview)
return preview
def conform(self, directory, templates): def conform(self, directory, templates):
"""Split each assets per blend and externalize preview""" """Split each assets per blend and externalize preview"""
@ -317,20 +346,20 @@ class ScanFolderLibrary(AssetLibraryAdapter):
self.copy_file(src_video_path, dst_video_path) self.copy_file(src_video_path, dst_video_path)
self.write_catalog(catalog_data, filepath=directory) self.write_catalog(catalog_data, filepath=directory)
'''
def fetch(self): def fetch(self):
"""Gather in a list all assets found in the folder""" """Gather in a list all assets found in the folder"""
print(f'Fetch Assets for {self.library.name}') print(f'Fetch Assets for {self.library.name}')
source_directory = Path(os.path.expandvars(self.source_directory)) source_directory = Path(self.source_directory)
template = Template(self.template) template_file = Template(self.template_file)
catalog_data = self.read_catalog(filepath=source_directory) catalog_data = self.read_catalog(directory=source_directory)
catalog_ids = {v['id']: {'path': k, 'name': v['name']} for k,v in catalog_data.items()} catalog_ids = {v['id']: k for k, v in catalog_data.items()}
cache = self.read_cache() or [] cache = self.read_cache() or []
print(f'Search for blend using glob template: {template.glob_pattern}') print(f'Search for blend using glob template: {template_file.glob_pattern}')
print(f'Scanning Folder {source_directory}...') print(f'Scanning Folder {source_directory}...')
#blend_files = list(source_directory.glob(template.glob_pattern)) #blend_files = list(source_directory.glob(template.glob_pattern))
@ -344,102 +373,71 @@ class ScanFolderLibrary(AssetLibraryAdapter):
#blend_paths = [] #blend_paths = []
new_cache = [] new_cache = []
for blend_file in template.glob(source_directory):#sorted(blend_files): for asset_path in template_file.glob(source_directory):#sorted(blend_files):
source_rel_path = self.prop_rel_path(blend_file, 'source_directory') source_rel_path = self.prop_rel_path(asset_path, 'source_directory')
modified = blend_file.stat().st_mtime_ns modified = asset_path.stat().st_mtime_ns
# Check if the asset description as already been cached
asset_description = next((a for a in cache if a['filepath'] == source_rel_path), None) asset_description = next((a for a in cache if a['filepath'] == source_rel_path), None)
if asset_description and asset_description['modified'] >= modified: if asset_description and asset_description['modified'] >= modified:
print(blend_file, 'is skipped because not modified') print(asset_path, 'is skipped because not modified')
new_cache.append(asset_description) new_cache.append(asset_description)
continue continue
rel_path = blend_file.relative_to(source_directory).as_posix() rel_path = asset_path.relative_to(source_directory).as_posix()
#field_values = re.findall(re_pattern, rel_path)[0] field_data = template_file.parse(rel_path)
#field_data = {k:v for k,v in zip(field_names, field_values)}
field_data = template.parse(rel_path)
if not field_data:
raise Exception()
#asset_data = (blend_file / prefs.template_description.format(name=name)).resolve()
catalogs = [v for k,v in sorted(field_data.items()) if k.isdigit()] catalogs = [v for k,v in sorted(field_data.items()) if k.isdigit()]
catalogs = [c.replace('_', ' ').title() for c in catalogs] catalogs = [c.replace('_', ' ').title() for c in catalogs]
asset_datas = {
"name": field_data['asset_name'],
"catalog": '/'.join(catalogs),
"assets": [],
'modified': modified
}
if self.data_type == 'FILE': if self.data_type == 'FILE':
name = field_data.get('name', blend_file.stem) asset_description = self.get_asset_description(asset_datas, asset_path)
image = self.get_path('image', name=name, asset_path=blend_file)
asset_description = dict(
filepath=source_rel_path,
modified=modified,
catalog='/'.join(catalogs),
tags=[],
type=self.data_type,
image=self.prop_rel_path(image, 'source_directory'),
name=name
)
new_cache.append(asset_description) new_cache.append(asset_description)
continue continue
#First Check if there is a asset_data .json # Now check if there is a asset description file
asset_description = self.read_asset_description_file(blend_file) asset_description_path = self.get_template_path(
self.template_description,
asset_datas['asset_name'],
asset_path,
asset_datas['catalog'])
if not asset_description: if asset_description_path and asset_description_path.exists():
# Scan the blend file for assets inside and write a custom asset description for info found new_cache.append(self.read_file(asset_description_path))
continue
print(f'Scanning blendfile {blend_file}...') # Scan the blend file for assets inside and write a custom asset description for info found
with bpy.data.libraries.load(str(blend_file), link=True, assets_only=True) as (data_from, data_to): print(f'Scanning blendfile {asset_path}...')
asset_names = getattr(data_from, self.data_types) assets = self.load_datablocks(asset_path, type=self.data_types, link=True, assets_only=True)
print(f'Found {len(asset_names)} {self.data_types} inside') print(f'Found {len(assets)} {self.data_types} inside')
setattr(data_to, self.data_types, asset_names) for asset in assets:
assets = getattr(data_to, self.data_types) catalog_path = catalog_ids.get(asset.asset_data.catalog_id)
asset_description = dict( if not catalog_path:
filepath=source_rel_path, print(f'No catalog found for asset {asset.name}')
modified=modified, catalog_path = asset_path.relative_to(self.source_directory).as_posix()
assets=[]
)
for asset in assets: asset_datas['assets'] += [dict(
asset_catalog_data = catalog_ids.get(asset.asset_data.catalog_id) catalog=catalog_path,
tags=asset.asset_data.tags.keys(),
metadata=dict(asset.asset_data),
type=self.data_type,
name=asset.name
)]
if not asset_catalog_data: getattr(bpy.data, self.data_types).remove(asset)
print(f'No catalog found for asset {asset.name}')
asset_catalog_data = {"path": blend_file.relative_to(self.source_directory).as_posix()}
catalog_path = asset_catalog_data['path'] asset_description = self.get_asset_description(asset_datas, asset_path)
image_path = self.get_path('image', asset.name, catalog_path)
image = self.prop_rel_path(image_path, 'source_directory')
# Write image only if no image was found
if not image_path.exists():
image_path = self.get_cache_image_path(asset.name, catalog_path)
image = self.prop_rel_path(image_path, 'library_path')
self.write_preview(asset.preview, image_path)
video_path = self.get_path('video', asset.name, catalog_path)
video = self.prop_rel_path(video_path, 'source_directory')
asset_data = dict(
filepath=self.prop_rel_path(blend_file, 'source_directory'),
modified=modified,
catalog=catalog_path,
tags=asset.asset_data.tags.keys(),
type=self.data_type,
image=image,
video=video,
name=asset.name
)
asset_description['assets'].append(asset_data)
getattr(bpy.data, self.data_types).remove(asset)
new_cache.append(asset_description) new_cache.append(asset_description)

View File

@ -16,6 +16,7 @@ if 'bpy' in locals():
#importlib.reload(build_collection_blends) #importlib.reload(build_collection_blends)
#importlib.reload(create_collection_library) #importlib.reload(create_collection_library)
import bpy
def register(): def register():
operators.register() operators.register()

View File

@ -42,43 +42,29 @@ class ASSETLIB_OT_load_asset(Operator):
print('Load Asset') print('Load Asset')
lib = get_active_library() lib = get_active_library()
print(lib, lib.data_type)
# dir(asset) : 'asset_data', 'bl_rna', 'id_type', 'local_id', 'name', 'preview_icon_id', 'relative_path', 'rna_type']
# dir(asset.asset_data) : 'active_tag', 'author', 'bl_rna', 'catalog_id', 'catalog_simple_name', 'description', 'rna_type', 'tags']
## get source path
# asset_file_handle = context.asset_file_handle
# if asset_file_handle is None:
# return {'CANCELLED'}
# if asset_file_handle.local_id:
# return {'CANCELLED'}
# asset_library_ref = context.asset_library_ref
# source_directory = bpy.types.AssetHandle.get_full_library_path(
# asset_file_handle, asset_library_ref
# )
asset = context.active_file asset = context.active_file
if not asset: if not asset:
self.report({"ERROR"}, 'No asset selected') self.report({"ERROR"}, 'No asset selected')
return {'CANCELLED'} return {'CANCELLED'}
active_lib = lib.adapter.get_active_asset_library()
asset_path = asset.asset_data['filepath'] asset_path = asset.asset_data['filepath']
fp = lib.adapter.format_path(asset_path) asset_path = active_lib.adapter.format_path(asset_path)
name = asset.name name = asset.name
## set mode to object ## set mode to object
if context.mode != 'OBJECT': if context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
## get the real direct path with expand_var if not Path(asset_path).exists():
print('path expanded: ', fp) self.report({'ERROR'}, f'Not exists: {asset_path}')
if not Path(fp).exists():
self.report({'ERROR'}, f'Not exists: {fp}')
return {'CANCELLED'} return {'CANCELLED'}
res = load_col(fp, name, link=True, override=True, rig_pattern='*_rig') print('Load collection', asset_path, name)
res = load_col(asset_path, name, link=True, override=True, rig_pattern='*_rig')
if res: if res:
if res.type == 'ARMATURE': if res.type == 'ARMATURE':
self.report({'INFO'}, f'Override rig {res.name}') self.report({'INFO'}, f'Override rig {res.name}')

Binary file not shown.

View File

@ -13,6 +13,7 @@ from bpy_extras import asset_utils
from asset_library.constants import RESOURCES_DIR from asset_library.constants import RESOURCES_DIR
#from asset_library.common.file_utils import no #from asset_library.common.file_utils import no
from os.path import abspath from os.path import abspath
import subprocess
class attr_set(): class attr_set():
@ -328,13 +329,10 @@ def split_path(path) :
def load_datablocks(src, names=None, type='objects', link=True, expr=None) -> list: def load_datablocks(src, names=None, type='objects', link=True, expr=None, assets_only=False) -> list:
return_list = not isinstance(names, str) return_list = not isinstance(names, str)
names = names or [] names = names or []
if type.isupper():
type = f'{type.lower()}s'
if not isinstance(names, (list, tuple)): if not isinstance(names, (list, tuple)):
names = [names] names = [names]
@ -342,7 +340,7 @@ def load_datablocks(src, names=None, type='objects', link=True, expr=None) -> li
pattern = expr pattern = expr
expr = lambda x : fnmatch(x, pattern) expr = lambda x : fnmatch(x, pattern)
with bpy.data.libraries.load(str(src), link=link) as (data_from, data_to): with bpy.data.libraries.load(str(src), link=link,assets_only=assets_only) as (data_from, data_to):
datablocks = getattr(data_from, type) datablocks = getattr(data_from, type)
if expr: if expr:
names += [i for i in datablocks if expr(i)] names += [i for i in datablocks if expr(i)]
@ -384,13 +382,7 @@ def load_col(filepath, name, link=True, override=True, rig_pattern=None, context
# return data_to.collections[0] # return data_to.collections[0]
context = context or bpy.context context = context or bpy.context
collections = load_datablocks(filepath, name, link=link, type='collections') col = load_datablocks(filepath, name, link=link, type='collections')
if not collections:
print(f'No collection "{name}" found in: {filepath}')
return
col = collections[0]
print('collection:', col.name)
## create instance object ## create instance object
inst = bpy.data.objects.new(col.name, None) inst = bpy.data.objects.new(col.name, None)

View File

@ -180,7 +180,7 @@ def get_asset_source(replace_local=False):
source_path = re.sub(actionlib_dir_local, actionlib_dir, source_path) source_path = re.sub(actionlib_dir_local, actionlib_dir, source_path)
return source_path return source_path
"""" """
''' '''
def get_catalog_path(filepath=None): def get_catalog_path(filepath=None):
filepath = filepath or bpy.data.filepath filepath = filepath or bpy.data.filepath

BIN
common/preview.blend Normal file

Binary file not shown.

View File

@ -9,6 +9,8 @@ if 'bpy' in locals():
importlib.reload(gui) importlib.reload(gui)
importlib.reload(keymaps) importlib.reload(keymaps)
import bpy
def register(): def register():
operators.register() operators.register()
keymaps.register() keymaps.register()

View File

@ -14,13 +14,21 @@ from bpy.types import (
from bpy_extras import asset_utils from bpy_extras import asset_utils
from asset_library.common.bl_utils import get_object_libraries, get_addon_prefs from asset_library.common.bl_utils import get_object_libraries, get_addon_prefs
from asset_library.common.functions import get_active_library
def draw_context_menu(self, context): def draw_context_menu(layout):
layout = self.layout
#asset = context.active_file #asset = context.active_file
layout.operator_context = "INVOKE_DEFAULT"
lib = get_active_library()
filepath = lib.adapter.get_active_asset_path()
layout.operator("assetlib.open_blend_file", text="Open Blend File")#.filepath = asset.asset_data['filepath'] layout.operator("assetlib.open_blend_file", text="Open Blend File")#.filepath = asset.asset_data['filepath']
op = layout.operator("wm.link", text="Link")
op.filepath = str(filepath)
op = layout.operator("wm.append", text="Append")
op.filepath = str(filepath)
def draw_header(layout): def draw_header(layout):

View File

@ -36,9 +36,9 @@ class ASSETLIB_OT_open_blend_file(Operator):
def execute(self, context: Context) -> Set[str]: def execute(self, context: Context) -> Set[str]:
lib = get_active_library() lib = get_active_library()
print(lib, lib.data_type)
filepath = context.active_file.asset_data['filepath'] filepath = lib.get_active_asset_path()
open_blender_file(filepath) open_blender_file(filepath)
return {'FINISHED'} return {'FINISHED'}

BIN
file/preview.blend Normal file

Binary file not shown.

View File

@ -302,7 +302,7 @@ class ASSETLIB_OT_bundle_library(Operator):
blocking : BoolProperty(default=False) blocking : BoolProperty(default=False)
mode : EnumProperty(items=[(i.replace(' ', '_').upper(), i, '') for i in ('None', 'All', 'Auto Bundle')], default='NONE') mode : EnumProperty(items=[(i.replace(' ', '_').upper(), i, '') for i in ('None', 'All', 'Auto Bundle')], default='NONE')
directory : StringProperty(subtype='DIR_PATH') directory : StringProperty(subtype='DIR_PATH')
conform : BoolProperty(default=False) #conform : BoolProperty(default=False)
#def refresh(self): #def refresh(self):
# for area in suitable_areas(bpy.context.screen): # for area in suitable_areas(bpy.context.screen):
# bpy.ops.asset.library_refresh({"area": area, 'region': area.regions[3]}) # bpy.ops.asset.library_refresh({"area": area, 'region': area.regions[3]})
@ -327,10 +327,6 @@ class ASSETLIB_OT_bundle_library(Operator):
print(f'Bundle Libraries: {[l.name for l in libs]}') print(f'Bundle Libraries: {[l.name for l in libs]}')
adapter = "lib.adapter"
if self.conform:
adapter = "lib.conform.adapter"
script_code = dedent(f""" script_code = dedent(f"""
import bpy import bpy
prefs = bpy.context.preferences.addons["asset_library"].preferences prefs = bpy.context.preferences.addons["asset_library"].preferences
@ -338,7 +334,7 @@ class ASSETLIB_OT_bundle_library(Operator):
for lib_data in {lib_datas}: for lib_data in {lib_datas}:
lib = prefs.env_libraries.add() lib = prefs.env_libraries.add()
lib.set_dict(lib_data) lib.set_dict(lib_data)
{adapter}.bundle(cache_diff='{self.diff}') lib.adapter.bundle(cache_diff='{self.diff}')
bpy.ops.wm.quit_blender() bpy.ops.wm.quit_blender()
""") """)
@ -400,7 +396,7 @@ class ASSETLIB_OT_diff(Operator):
return {'FINISHED'} return {'FINISHED'}
'''
class ASSETLIB_OT_conform_library(Operator): class ASSETLIB_OT_conform_library(Operator):
bl_idname = "assetlib.conform_library" bl_idname = "assetlib.conform_library"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@ -445,7 +441,7 @@ class ASSETLIB_OT_conform_library(Operator):
def invoke(self, context, event): def invoke(self, context, event):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
'''
class ASSETLIB_OT_generate_previews(Operator): class ASSETLIB_OT_generate_previews(Operator):
bl_idname = "assetlib.generate_previews" bl_idname = "assetlib.generate_previews"
@ -453,7 +449,7 @@ class ASSETLIB_OT_generate_previews(Operator):
bl_label = "Generate Previews" bl_label = "Generate Previews"
bl_description = "Generate and write the image for assets" bl_description = "Generate and write the image for assets"
diff : StringProperty() cache : StringProperty()
preview_blend : StringProperty() preview_blend : StringProperty()
name : StringProperty() name : StringProperty()
blocking : BoolProperty(default=True) blocking : BoolProperty(default=True)
@ -476,6 +472,9 @@ class ASSETLIB_OT_generate_previews(Operator):
# subprocess.call(cmd) # subprocess.call(cmd)
preview_blend = self.preview_blend or lib.adapter.preview_blend preview_blend = self.preview_blend or lib.adapter.preview_blend
if not preview_blend or not Path(preview_blend).exists():
preview_blend = MODULE_DIR / 'common' / 'preview.blend'
script_path = Path(bpy.app.tempdir) / 'generate_previews.py' script_path = Path(bpy.app.tempdir) / 'generate_previews.py'
script_code = dedent(f""" script_code = dedent(f"""
import bpy import bpy
@ -484,7 +483,7 @@ class ASSETLIB_OT_generate_previews(Operator):
lib.set_dict({lib.to_dict()}) lib.set_dict({lib.to_dict()})
bpy.ops.wm.open_mainfile(filepath='{preview_blend}', load_ui=True) bpy.ops.wm.open_mainfile(filepath='{preview_blend}', load_ui=True)
lib.conform.adapter.generate_previews() lib.adapter.generate_previews(cache='{self.cache}')
""") """)
script_path.write_text(script_code) script_path.write_text(script_code)
@ -609,7 +608,7 @@ classes = (
ASSETLIB_OT_bundle_library, ASSETLIB_OT_bundle_library,
ASSETLIB_OT_clear_asset, ASSETLIB_OT_clear_asset,
ASSETLIB_OT_edit_data, ASSETLIB_OT_edit_data,
ASSETLIB_OT_conform_library, #ASSETLIB_OT_conform_library,
ASSETLIB_OT_reload_addon ASSETLIB_OT_reload_addon
) )

View File

@ -83,7 +83,7 @@ class AssetLibraryAdapters(PropertyGroup):
def __iter__(self): def __iter__(self):
return (getattr(self, p) for p in self.bl_rna.properties.keys() if p not in ('rna_type', 'name')) return (getattr(self, p) for p in self.bl_rna.properties.keys() if p not in ('rna_type', 'name'))
'''
class ConformAssetLibrary(PropertyGroup): class ConformAssetLibrary(PropertyGroup):
adapters : bpy.props.PointerProperty(type=AssetLibraryAdapters) adapters : bpy.props.PointerProperty(type=AssetLibraryAdapters)
adapter_name : EnumProperty(items=get_adapter_items) adapter_name : EnumProperty(items=get_adapter_items)
@ -117,16 +117,19 @@ class ConformAssetLibrary(PropertyGroup):
del data['adapters'] del data['adapters']
return data return data
'''
class AssetLibrary(PropertyGroup): class AssetLibrary(PropertyGroup):
name : StringProperty(name='Name', default='Action Library', update=update_library_path) name : StringProperty(name='Name', default='Action Library', update=update_library_path)
id : StringProperty() id : StringProperty()
auto_bundle : BoolProperty(name='Auto Bundle', default=True) auto_bundle : BoolProperty(name='Auto Bundle', default=False)
expand : BoolProperty(name='Expand', default=False) expand : BoolProperty(name='Expand', default=False)
use : BoolProperty(name='Use', default=True, update=update_library_path) use : BoolProperty(name='Use', default=True, update=update_library_path)
data_type : EnumProperty(name='Type', items=DATA_TYPE_ITEMS, default='COLLECTION') data_type : EnumProperty(name='Type', items=DATA_TYPE_ITEMS, default='COLLECTION')
template_image : StringProperty(default='', description='../{name}_image.png')
template_video : StringProperty(default='', description='../{name}_video.mov')
template_description : StringProperty(default='', description='../{name}_asset_description.json')
bundle_directory : StringProperty( bundle_directory : StringProperty(
name="Bundle Directory", name="Bundle Directory",
@ -153,7 +156,7 @@ class AssetLibrary(PropertyGroup):
template: StringProperty() template: StringProperty()
expand_extra : BoolProperty(name='Expand', default=False) expand_extra : BoolProperty(name='Expand', default=False)
blend_depth : IntProperty(name='Blend Depth', default=0) blend_depth : IntProperty(name='Blend Depth', default=1)
# source_directory : StringProperty( # source_directory : StringProperty(
# name="Path", # name="Path",
@ -166,8 +169,7 @@ class AssetLibrary(PropertyGroup):
#adapter : EnumProperty(items=adapter_ITEMS) #adapter : EnumProperty(items=adapter_ITEMS)
adapters : bpy.props.PointerProperty(type=AssetLibraryAdapters) adapters : bpy.props.PointerProperty(type=AssetLibraryAdapters)
adapter_name : EnumProperty(items=get_adapter_items) adapter_name : EnumProperty(items=get_adapter_items)
parent : StringProperty()
conform: bpy.props.PointerProperty(type=ConformAssetLibrary)
# data_file_path : StringProperty( # data_file_path : StringProperty(
# name="Path", # name="Path",
@ -175,8 +177,6 @@ class AssetLibrary(PropertyGroup):
# default='', # default='',
# ) # )
#expand_conform : BoolProperty(name='Expand Conform', default=False)
#def __init__(self): #def __init__(self):
# self.adapters.parent = self # self.adapters.parent = self
@ -185,9 +185,17 @@ class AssetLibrary(PropertyGroup):
prefs = get_addon_prefs() prefs = get_addon_prefs()
return [l for l in prefs.libraries if l != self and (l.library_path == self.library_path)] return [l for l in prefs.libraries if l != self and (l.library_path == self.library_path)]
@property
def child_libraries(self):
prefs = get_addon_prefs()
return [l for l in prefs.libraries if l != self and (l.parent == self.name)]
@property @property
def data_types(self): def data_types(self):
return f'{self.data_type.lower()}s' data_type = self.data_type
if data_type == 'FILE':
data_type = 'COLLECTION'
return f'{data_type.lower()}s'
@property @property
def adapter(self): def adapter(self):
@ -217,7 +225,7 @@ class AssetLibrary(PropertyGroup):
# library_name = norm_str(library_name) # library_name = norm_str(library_name)
if self.use_custom_bundle_directory: if self.use_custom_bundle_directory:
return Path(self.custom_bundle_directory, library_name).resolve() return Path(self.custom_bundle_directory).resolve()
else: else:
library_name = norm_str(library_name) library_name = norm_str(library_name)
return Path(prefs.bundle_directory, library_name).resolve() return Path(prefs.bundle_directory, library_name).resolve()
@ -229,29 +237,6 @@ class AssetLibrary(PropertyGroup):
return self.name return self.name
@property
def template_image(self):
prefs = get_addon_prefs()
return prefs.template_image
@property
def template_video(self):
prefs = get_addon_prefs()
return prefs.template_video
@property
def template_description(self):
prefs = get_addon_prefs()
return prefs.template_description
#@property
#def catalog_path(self):
# return get_catalog_path(self.library_path)
@property
def options(self):
return {k: getattr(self.adapter, k) for k, v in self.options.bl_rna.properties.keys() if p !='rna_type'}
def clear_library_path(self): def clear_library_path(self):
#print('Clear Library Path', self.name) #print('Clear Library Path', self.name)
@ -348,7 +333,7 @@ class AssetLibrary(PropertyGroup):
data['adapter']['name'] = data.pop('adapter_name') data['adapter']['name'] = data.pop('adapter_name')
del data['adapters'] del data['adapters']
data['conform'] = self.conform.to_dict() #data['conform'] = self.conform.to_dict()
return data return data
@ -448,6 +433,7 @@ class AssetLibrary(PropertyGroup):
layout.separator(factor=3) layout.separator(factor=3)
"""
def draw_extra(self, layout): def draw_extra(self, layout):
#box = layout.box() #box = layout.box()
@ -503,15 +489,14 @@ class AssetLibrary(PropertyGroup):
col.separator() col.separator()
"""
def draw(self, layout): def draw(self, layout):
prefs = get_addon_prefs() prefs = get_addon_prefs()
#box = layout.box()
box = layout.box() row = layout.row(align=True)
row = box.row(align=True)
#row.use_property_split = False #row.use_property_split = False
#row.alignment = 'LEFT' #row.alignment = 'LEFT'
@ -544,7 +529,7 @@ class AssetLibrary(PropertyGroup):
sub_row.label(icon='FAKE_USER_ON') sub_row.label(icon='FAKE_USER_ON')
if self.expand: if self.expand:
col = box.column(align=False) col = layout.column(align=False)
col.use_property_split = True col.use_property_split = True
#row = col.row(align=True) #row = col.row(align=True)
@ -564,12 +549,22 @@ class AssetLibrary(PropertyGroup):
label='Custom Bundle Directory', label='Custom Bundle Directory',
) )
col.prop(self, "blend_depth")
subcol = col.column(align=True)
subcol.prop(self, "template_description", text='Template Description', icon='COPY_ID')
subcol.prop(self, "template_image", text='Template Image', icon='COPY_ID')
subcol.prop(self, "template_video", text='Template Video', icon='COPY_ID')
if self.adapter: if self.adapter:
col.separator() col.separator()
self.adapter.draw_prefs(col) self.adapter.draw_prefs(col)
for lib in self.child_libraries:
lib.draw(layout)
col.separator() col.separator()
self.draw_extra(col)
@ -662,10 +657,7 @@ class AssetLibraryPrefs(AddonPreferences):
update=update_all_library_path update=update_all_library_path
) )
#use_single_path : BoolProperty(default=True)
#template_description : StringProperty(default='../{name}_asset_description.json')
#template_image : StringProperty(default='../{name}_image.png')
#template_video : StringProperty(default='../{name}_video.mov')
config_directory : StringProperty( config_directory : StringProperty(
name="Config Path", name="Config Path",
@ -773,8 +765,11 @@ class AssetLibraryPrefs(AddonPreferences):
col.operator("assetlib.add_user_library", text='Bundle All Libraries', icon='MOD_BUILD') col.operator("assetlib.add_user_library", text='Bundle All Libraries', icon='MOD_BUILD')
for lib in self.libraries:# list(self.env_libraries) + list(self.user_libraries): for lib in self.libraries:# list(self.env_libraries) + list(self.user_libraries):
if lib.parent:
continue
lib.draw(main_col) box = main_col.box()
lib.draw(box)
row = main_col.row() row = main_col.row()
row.alignment = 'RIGHT' row.alignment = 'RIGHT'
@ -783,7 +778,7 @@ class AssetLibraryPrefs(AddonPreferences):
classes = [ classes = [
AssetLibraryAdapters, AssetLibraryAdapters,
ConformAssetLibrary, #ConformAssetLibrary,
AssetLibrary, AssetLibrary,
AssetLibraryPrefs, AssetLibraryPrefs,
] ]