continue refactoring
parent
fc405797d9
commit
575bbade7b
|
@ -1032,7 +1032,7 @@ class ACTIONLIB_OT_store_anim_pose(Operator):
|
|||
modified=time.time_ns()
|
||||
)
|
||||
|
||||
lib.adapter.write_asset_description(asset_description, asset_path)
|
||||
lib.adapter.write_description_file(asset_description, asset_path)
|
||||
|
||||
# Restore action and cleanup
|
||||
ob.animation_data.action = current_action
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
from asset_library.common.functions import (read_catalog, write_catalog, norm_asset_datas, get_catalog_path)
|
||||
from asset_library.common.functions import (read_catalog, write_catalog, norm_asset_datas)
|
||||
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.template import Template
|
||||
from asset_library.constants import (PREVIEW_ASSETS_SCRIPT, MODULE_DIR)
|
||||
|
||||
from asset_library import (action, collection, file)
|
||||
|
||||
|
@ -18,6 +19,7 @@ import json
|
|||
import uuid
|
||||
import time
|
||||
from functools import partial
|
||||
import subprocess
|
||||
|
||||
|
||||
class AssetLibraryAdapter(PropertyGroup):
|
||||
|
@ -26,7 +28,7 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
name = "Base Adapter"
|
||||
#library = None
|
||||
|
||||
bundle_directory : StringProperty()
|
||||
#bundle_directory : StringProperty()
|
||||
|
||||
@property
|
||||
def library(self):
|
||||
|
@ -37,29 +39,9 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
if lib.conform.adapter == self:
|
||||
return lib
|
||||
|
||||
@property
|
||||
def library_path(self):
|
||||
return self.library.library_path
|
||||
|
||||
@property
|
||||
def image_template(self):
|
||||
return Template(self.library.image_template)
|
||||
|
||||
@property
|
||||
def video_template(self):
|
||||
return Template(self.library.video_template)
|
||||
|
||||
@property
|
||||
def asset_description_template(self):
|
||||
return Template(self.library.asset_description_template)
|
||||
|
||||
@property
|
||||
def data_type(self):
|
||||
return self.library.data_type
|
||||
|
||||
@property
|
||||
def data_types(self):
|
||||
return self.library.data_types
|
||||
#@property
|
||||
#def library_path(self):
|
||||
# return self.library.library_path
|
||||
|
||||
@property
|
||||
def is_conform(self):
|
||||
|
@ -70,29 +52,70 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
if lib.conform.adapter == self:
|
||||
return True
|
||||
|
||||
@property
|
||||
def target_directory(self):
|
||||
if self.is_conform:
|
||||
return self.library.conform.directory
|
||||
|
||||
return self.library.bundle_dir
|
||||
|
||||
@property
|
||||
def blend_depth(self):
|
||||
if self.is_conform:
|
||||
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 externalize_data(self):
|
||||
return self.library.externalize_data
|
||||
def template_video(self):
|
||||
return Template(self.library.conform.template_video)
|
||||
|
||||
@property
|
||||
def catalog_path(self):
|
||||
return self.library.catalog_path
|
||||
def template_description(self):
|
||||
return Template(self.library.conform.template_description)
|
||||
|
||||
|
||||
def get_catalog_path(self, filepath):
|
||||
return get_catalog_path(filepath)
|
||||
@property
|
||||
def data_type(self):
|
||||
return self.library.data_type
|
||||
|
||||
@property
|
||||
def data_types(self):
|
||||
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):
|
||||
directory = directory or self.target_directory
|
||||
return Path(directory, 'blender_assets.cats.txt')
|
||||
|
||||
@property
|
||||
def cache_file(self):
|
||||
return Path(self.library_path) / f"blender_assets.{self.library.id}.json"
|
||||
return Path(self.target_directory) / f"blender_assets.{self.library.id}.json"
|
||||
#return get_asset_datas_file(self.library_path)
|
||||
|
||||
@property
|
||||
def diff_file(self):
|
||||
return Path(bpy.app.tempdir, 'diff.json')
|
||||
|
||||
@property
|
||||
def preview_blend(self):
|
||||
return MODULE_DIR / self.data_type.lower() / "preview.blend"
|
||||
|
||||
@property
|
||||
def preview_assets_file(self):
|
||||
return Path(bpy.app.tempdir, "preview_assets_file.json")
|
||||
|
||||
@property
|
||||
def addon_prefs(self):
|
||||
return get_addon_prefs()
|
||||
|
@ -116,6 +139,12 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
def norm_file_name(self, name):
|
||||
return name.replace(' ', '_')
|
||||
|
||||
def read_file(self, file):
|
||||
return read_file(file)
|
||||
|
||||
def write_file(self, file, data):
|
||||
return write_file(file, data)
|
||||
|
||||
def copy_file(self, source, destination):
|
||||
src = Path(source)
|
||||
dst = Path(destination)
|
||||
|
@ -185,6 +214,31 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
|
||||
return asset_path
|
||||
|
||||
def get_template_path(self, template, name, asset_path, catalog):
|
||||
|
||||
if template.startswith('.'): #the template is relative
|
||||
template = Path(asset_path, template).as_posix()
|
||||
|
||||
params = {
|
||||
'name': name,
|
||||
'asset_path': Path(asset_path),
|
||||
'catalog': catalog,
|
||||
'catalog_name': catalog.replace('/', '_'),
|
||||
}
|
||||
|
||||
return self.format_path(template, **params)
|
||||
|
||||
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"""
|
||||
return self.get_template_path(self.library.conform.template_description, name, asset_path, catalog)
|
||||
|
||||
def get_image_path(self, name, asset_path, catalog) -> Path:
|
||||
return self.get_template_path(self.library.conform.template_image, name, asset_path, catalog)
|
||||
|
||||
def get_video_path(self, name, asset_path, catalog) -> Path:
|
||||
return self.get_template_path(self.library.conform.template_video, name, asset_path, catalog)
|
||||
|
||||
'''
|
||||
def get_path(self, type, name, asset_path, template=None) -> Path:
|
||||
if not template:
|
||||
template = getattr(self, f'{type}_template')
|
||||
|
@ -193,27 +247,40 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
template = Template(template)
|
||||
|
||||
filepath = Path(asset_path)
|
||||
return (filepath / template.format(name=name, path=Path(asset_path))).resolve()
|
||||
|
||||
params = {
|
||||
'bundle_dir': self.library.bundle_directory,
|
||||
'conform_dir': self.library.conform.directory,
|
||||
'rel_path': '',
|
||||
'catalog':'',
|
||||
'catalog_name':'',
|
||||
'name': name
|
||||
}
|
||||
|
||||
return self.format_path(template, params)#(filepath / template.format(name=name, path=Path(asset_path))).resolve()
|
||||
|
||||
#def get_image_path(self, name, asset_path):
|
||||
# filepath = Path(asset_path)
|
||||
# image_name = self._get_file_name(name, asset_path)
|
||||
# return (filepath / self.image_template.format(name=image_name)).resolve()
|
||||
# return (filepath / self.template_image.format(name=image_name)).resolve()
|
||||
|
||||
|
||||
def get_cache_image_path(self, name, catalog) -> Path:
|
||||
""""Get the the cache path of a image for asset without an externalized image"""
|
||||
name = self.norm_file_name(name)
|
||||
return Path(self.library_path, '.previews', f"{catalog.replace('/', '_')}_{name}").with_suffix(('.png'))
|
||||
|
||||
def get_cache_image(self, name, catalog):
|
||||
cache_image_path = self.get_cache_image_path(name, catalog)
|
||||
if cache_image_path.exists():
|
||||
return cache_image_path
|
||||
'''
|
||||
|
||||
#def get_video_path(self, name, asset_path):
|
||||
# filepath = Path(asset_path)
|
||||
# video_name = self._get_file_name(name, asset_path)
|
||||
# return (filepath / self.video_template.format(name=video_name)).resolve()
|
||||
|
||||
# return (filepath / self.template_video.format(name=video_name)).resolve()
|
||||
'''
|
||||
def get_image(self, name, asset_path):
|
||||
image_path = self.get_path('image', name, asset_path)
|
||||
if image_path.exists():
|
||||
|
@ -223,21 +290,19 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
video_path = self.get_path('video', name, asset_path)
|
||||
if video_path.exists():
|
||||
return video_path
|
||||
'''
|
||||
|
||||
def get_asset_description_path(self, asset_path) -> Path:
|
||||
""""Get the path of the json or yaml describing all assets data in onle file"""
|
||||
filepath = Path(asset_path)
|
||||
return (filepath / self.asset_description_template.format(name=filepath.stem)).resolve()
|
||||
|
||||
def read_asset_description(self, asset_path) -> dict:
|
||||
|
||||
def read_asset_description_file(self, asset_path) -> dict:
|
||||
"""Read the description file of the asset"""
|
||||
|
||||
asset_description_path = self.get_asset_description_path(asset_path)
|
||||
return read_file(asset_description_path)
|
||||
description_path = self.get_description_path(asset_path)
|
||||
return self.read_file(description_path)
|
||||
|
||||
def write_asset_description(self, asset_data, asset_path) -> None:
|
||||
asset_description_path = self.get_asset_description_path(asset_path)
|
||||
return write_file(asset_description_path, asset_data)
|
||||
def write_description_file(self, asset_data, asset_path) -> None:
|
||||
description_path = self.get_description_path(asset_path)
|
||||
return write_file(description_path, asset_data)
|
||||
|
||||
def write_asset(self, asset, asset_path):
|
||||
bpy.data.libraries.write(
|
||||
|
@ -247,27 +312,48 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
fake_user=True,
|
||||
compress=True
|
||||
)
|
||||
|
||||
|
||||
def read_catalog(self, filepath=None):
|
||||
"""Read the catalog file of the library bundle path or of the specified filepath"""
|
||||
def read_catalog(self, directory=None):
|
||||
"""Read the catalog file of the library target directory or of the specified directory"""
|
||||
catalog_path = self.get_catalog_path(directory)
|
||||
|
||||
catalog_path = self.catalog_path
|
||||
if filepath:
|
||||
catalog_path = self.get_catalog_path(filepath)
|
||||
return read_catalog(catalog_path)
|
||||
cat_data = {}
|
||||
|
||||
def write_catalog(self, catalog_data, filepath=None):
|
||||
"""Write the catalog file in the library bundle path or of the specified filepath"""
|
||||
for line in catalog_path.read_text(encoding="utf-8").split('\n'):
|
||||
if line.startswith(('VERSION', '#')) or not line:
|
||||
continue
|
||||
|
||||
cat_id, cat_path, cat_name = line.split(':')
|
||||
cat_data[cat_path] = {'id':cat_id, 'name':cat_name}
|
||||
|
||||
catalog_path = self.catalog_path
|
||||
if filepath:
|
||||
catalog_path = self.get_catalog_path(filepath)
|
||||
return cat_data
|
||||
|
||||
def write_catalog(self, catalog_data, directory=None):
|
||||
"""Write the catalog file in the library target directory or of the specified directory"""
|
||||
|
||||
return write_catalog(catalog_path, catalog_data)
|
||||
catalog_path = self.get_catalog_path(directory)
|
||||
|
||||
lines = ['VERSION 1', '']
|
||||
|
||||
# Add missing parents catalog
|
||||
norm_data = {}
|
||||
for cat_path, cat_data in catalog_data.items():
|
||||
norm_data[cat_path] = cat_data
|
||||
for p in Path(cat_path).parents[:-1]:
|
||||
if p in data or p in norm_data:
|
||||
continue
|
||||
|
||||
norm_data[p.as_posix()] = {'id': str(uuid.uuid4()), 'name': '-'.join(p.parts)}
|
||||
|
||||
for cat_path, cat_data in sorted(norm_data.items()):
|
||||
cat_name = cat_data['name'].replace('/', '-')
|
||||
lines.append(f"{cat_data['id']}:{cat_path}:{cat_name}")
|
||||
|
||||
print(f'Catalog writen at: {catalog_path}')
|
||||
catalog_path.write_text('\n'.join(lines), encoding="utf-8")
|
||||
|
||||
def read_cache(self):
|
||||
return read_file(self.cache_file)
|
||||
return self.read_file(self.cache_file)
|
||||
|
||||
def norm_asset_datas(self, asset_file_datas):
|
||||
''' Return a new flat list of asset data
|
||||
|
@ -326,8 +412,148 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
|
||||
return catalog_parts[:self.blend_depth]
|
||||
|
||||
#def transfert_preview(self, )
|
||||
|
||||
'''
|
||||
def generate_previews(self, assets, callback):
|
||||
def _generate_previews(assets, callback, src_assets=None):
|
||||
if src_assets:
|
||||
src_assets = []
|
||||
|
||||
if bpy.app.is_job_running('RENDER_PREVIEW'):
|
||||
print("Waiting for render...")
|
||||
return 0.2 # waiting time
|
||||
|
||||
while assets: # generate next preview
|
||||
asset = assets.pop()
|
||||
#print(f"Creating preview for world {world.name}...")
|
||||
|
||||
asset_path = asset.asset_data['filepath']
|
||||
src_asset = self.load_datablocks(asset_path, names=asset.name, link=False, type=self.data_types)
|
||||
if not src_asset:
|
||||
#print(f'No asset named {asset.name} in {asset_path]}')
|
||||
return
|
||||
|
||||
src_assets.append(src_asset)
|
||||
# # set image in the preview object's material
|
||||
# obj = bpy.context.active_object
|
||||
# image = world.node_tree.nodes['Environment Texture'].image
|
||||
# obj.material_slots[0].material.node_tree.nodes['Image Texture'].image = image
|
||||
if self.data_type == 'COLLECTION':
|
||||
asset.children.link(src_asset)
|
||||
|
||||
# start preview render
|
||||
with bpy.context.temp_override(id=asset):
|
||||
bpy.ops.ed.lib_id_generate_preview()
|
||||
return 0.2
|
||||
|
||||
for asset in src_asset:
|
||||
asset.user_clear()
|
||||
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|
||||
|
||||
callback()
|
||||
return None
|
||||
|
||||
assets = assets.copy()
|
||||
|
||||
# create preview images
|
||||
bpy.app.timers.register(
|
||||
functools.partial(
|
||||
_generate_previews,
|
||||
assets,
|
||||
callback
|
||||
)
|
||||
)
|
||||
'''
|
||||
def generate_preview(self, asset_description):
|
||||
"""Only generate preview when conforming a library"""
|
||||
|
||||
#print('generate_preview', filepath, asset_names, data_type)
|
||||
|
||||
scn = bpy.context.scene
|
||||
#Creating the preview for collection, object or material
|
||||
camera = scn.camera
|
||||
vl = bpy.context.view_layer
|
||||
|
||||
data_type = self.data_type #asset_description['data_type']
|
||||
asset_path = asset_description['filepath']
|
||||
asset_data_names = {}
|
||||
for asset_data in asset_description['assets']:
|
||||
|
||||
name = asset_data['name']
|
||||
catalog = asset_data['catalog']
|
||||
|
||||
image_path = self.get_image_path(name, asset_path, catalog)
|
||||
if image_path.exists():
|
||||
continue
|
||||
|
||||
#Store in a dict all asset_data that does not have preview
|
||||
asset_data_names[name] = dict(asset_data, image_path=image_path)
|
||||
|
||||
if not asset_data_names:
|
||||
# No preview to generate
|
||||
return
|
||||
|
||||
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 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.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)
|
||||
|
||||
def generate_previews(self):
|
||||
cache = self.fetch()
|
||||
|
||||
#cache_diff.sort(key=lambda x :x['filepath'])
|
||||
#blend_groups = groupby(cache_diff, key=lambda x :x['filepath'])
|
||||
|
||||
#TODO Support all multiple data_type
|
||||
for asset_description in cache:
|
||||
self.generate_preview(asset_description)
|
||||
|
||||
# filepath = asset_description['filepath']
|
||||
|
||||
# asset_datas = asset_description["assets"]
|
||||
|
||||
# asset_datas.sort(key=lambda x :x.get('type', self.data_type))
|
||||
# data_type_groups = groupby(asset_datas, key=lambda x :x.get('type', self.data_type))
|
||||
|
||||
# for data_type, same_type_asset_datas in data_type_groups:
|
||||
|
||||
# asset_names = [a['name'] for a in same_type_asset_datas]
|
||||
# self.generate_preview(filepath, asset_names, data_type)
|
||||
|
||||
def set_asset_preview(self, asset, asset_data):
|
||||
"""Load an externalize image as preview for an asset"""
|
||||
'''Load an externalize image as preview for an asset'''
|
||||
|
||||
image_path = Path(asset_data['image'])
|
||||
if not image_path.is_absolute():
|
||||
|
@ -339,34 +565,52 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
bpy.ops.ed.lib_id_load_custom_preview(
|
||||
filepath=str(image_path)
|
||||
)
|
||||
return
|
||||
|
||||
if asset.preview:
|
||||
return
|
||||
|
||||
return asset.preview
|
||||
|
||||
return
|
||||
|
||||
#Creating the preview for collection, object or material
|
||||
src_asset = self.load_datablocks(asset_data['filepath'], names=asset_data['name'], link=False, type=self.data_types)
|
||||
if not src_asset:
|
||||
print(f'No asset named {asset_data["name"]} in {asset_data["filepath"]}')
|
||||
return
|
||||
|
||||
bpy.ops.ed.lib_id_generate_preview({"id": src_asset})
|
||||
#time.sleep(0.01)
|
||||
if not self.data_type == 'COLLECTION':
|
||||
print(f'Generate preview of type {self.data_type} not supported yet')
|
||||
return
|
||||
|
||||
#Transfering pixels between previews
|
||||
w, h = src_asset.preview.image_size
|
||||
pixels = [0] * (w*h*4)
|
||||
src_asset.preview.image_pixels_float.foreach_get(pixels)
|
||||
# asset.children.link(src_asset)
|
||||
# bpy.ops.ed.lib_id_generate_preview({"id": asset})
|
||||
|
||||
asset.preview_ensure()
|
||||
asset.preview.image_size = src_asset.preview.image_size
|
||||
asset.preview.image_pixels_float.foreach_set(pixels)
|
||||
# while bpy.app.is_job_running("RENDER_PREVIEW"):
|
||||
# print(bpy.app.is_job_running("RENDER_PREVIEW"))
|
||||
# time.sleep(0.2)
|
||||
|
||||
# getattr(bpy.data, self.data_types).remove(src_asset)
|
||||
# return asset.preview
|
||||
#src_asset.user_clear()
|
||||
#return src_asset
|
||||
|
||||
#asset.children.unlink(src_asset)
|
||||
#getattr(bpy.data, self.data_types).remove(src_asset)
|
||||
# time.sleep(1)
|
||||
|
||||
|
||||
# #Transfering pixels between previews
|
||||
# w, h = src_asset.preview.image_size
|
||||
# pixels = [0] * (w*h*4)
|
||||
# src_asset.preview.image_pixels_float.foreach_get(pixels)
|
||||
|
||||
# asset.preview_ensure()
|
||||
# asset.preview.image_size = src_asset.preview.image_size
|
||||
# asset.preview.image_pixels_float.foreach_set(pixels)
|
||||
|
||||
#print('pixels transfered')
|
||||
|
||||
bpy.app.timers.register(partial(getattr(bpy.data, self.data_types).remove, src_asset), first_interval=1)
|
||||
|
||||
#getattr(bpy.data, self.data_types).remove(src_asset)
|
||||
#bpy.app.timers.register(partial(getattr(bpy.data, self.data_types).remove, src_asset), first_interval=1)
|
||||
|
||||
|
||||
|
||||
def set_asset_catalog(self, asset, asset_data, catalog_data):
|
||||
|
@ -405,6 +649,10 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
continue
|
||||
asset.asset_data.tags.new(tag, skip_if_exists=True)
|
||||
|
||||
def set_asset_description(self, asset, asset_data):
|
||||
"""Set asset description base on provided data"""
|
||||
asset.asset_data.description = asset_data.get('description', '')
|
||||
|
||||
def bundle(self, cache_diff=None):
|
||||
"""Group all new assets in one or multiple blends for the asset browser"""
|
||||
|
||||
|
@ -412,7 +660,9 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
print(f'{self.data_type} is not supported yet')
|
||||
return
|
||||
|
||||
lib_path = self.library_path
|
||||
target_dir = self.target_directory
|
||||
|
||||
|
||||
catalog_data = self.read_catalog() #TODO remove unused catalog
|
||||
|
||||
write_cache = False
|
||||
|
@ -423,11 +673,18 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
# Only write complete cache at the end
|
||||
write_cache = True
|
||||
|
||||
self.generate_previews()
|
||||
|
||||
elif isinstance(cache_diff, (Path, str)):
|
||||
cache_diff = json.loads(Path(cache_diff).read_text(encoding='utf-8'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if self.blend_depth == 0:
|
||||
groups = [(cache_diff)]
|
||||
raise Exception('Blender depth must be 1 at min')
|
||||
#groups = [(cache_diff)]
|
||||
else:
|
||||
cache_diff.sort(key=self.group_key)
|
||||
groups = groupby(cache_diff, key=self.group_key)
|
||||
|
@ -440,9 +697,10 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
return
|
||||
|
||||
i = 0
|
||||
#assets_to_preview = []
|
||||
for sub_path, asset_datas in groups:
|
||||
blend_name = sub_path[-1].replace(' ', '_').lower()
|
||||
blend_path = Path(lib_path, *sub_path, blend_name).with_suffix('.blend')
|
||||
blend_path = Path(target_dir, *sub_path, blend_name).with_suffix('.blend')
|
||||
|
||||
if blend_path.exists():
|
||||
print(f'Opening existing bundle blend: {blend_path}')
|
||||
|
@ -471,9 +729,10 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
elif operation == 'ADD' or not asset:
|
||||
if asset:
|
||||
#raise Exception(f"Asset {asset_data['name']} Already in Blend")
|
||||
print(f"Asset {asset_data['name']} Already in Blend")
|
||||
getattr(bpy.data, self.data_types).remove(asset)
|
||||
|
||||
#print(f"INFO: Add new asset: {asset_data['name']}")
|
||||
print(f"INFO: Add new asset: {asset_data['name']}")
|
||||
asset = getattr(bpy.data, self.data_types).new(name=asset_data['name'])
|
||||
else:
|
||||
print(f'operation {operation} not supported should be in (ADD, REMOVE, MODIFIED)')
|
||||
|
@ -482,26 +741,36 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
asset.asset_mark()
|
||||
|
||||
self.set_asset_preview(asset, asset_data)
|
||||
|
||||
#if not asset_preview:
|
||||
# assets_to_preview.append((asset_data['filepath'], asset_data['name'], asset_data['data_type']))
|
||||
#if self.externalize_data:
|
||||
# self.write_preview(preview, filepath)
|
||||
|
||||
self.set_asset_catalog(asset, asset_data, catalog_data)
|
||||
self.set_asset_metadata(asset, asset_data)
|
||||
self.set_asset_tags(asset, asset_data)
|
||||
asset.asset_data.description = asset_data.get('description', '')
|
||||
self.set_asset_description(asset, asset_data)
|
||||
|
||||
|
||||
i += 1
|
||||
|
||||
#self.write_asset_preview_file()
|
||||
|
||||
|
||||
|
||||
print(f'Saving Blend to {blend_path}')
|
||||
|
||||
blend_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=str(blend_path), compress=True)
|
||||
#blend_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
#bpy.ops.wm.save_as_mainfile(filepath=str(blend_path), compress=True)
|
||||
|
||||
#if write_cache:
|
||||
# self.write_cache(cache)
|
||||
|
||||
#self.write_catalog(catalog_data)
|
||||
self.write_catalog(catalog_data)
|
||||
|
||||
|
||||
bpy.ops.wm.quit_blender()
|
||||
|
||||
def norm_cache(self, cache):
|
||||
|
@ -566,4 +835,11 @@ class AssetLibraryAdapter(PropertyGroup):
|
|||
layout.prop(self, k, text=bpy.path.display_name(k))
|
||||
|
||||
def format_path(self, template, **kargs):
|
||||
return Template(template).format(self.to_dict(), **kargs).resolve()
|
||||
|
||||
params = dict(self.to_dict(),
|
||||
bundle_dir=Path(self.library.bundle_directory),
|
||||
conform_dir=Path(self.library.conform.directory),
|
||||
**kargs
|
||||
)
|
||||
|
||||
return Template(template).format(params).resolve()
|
|
@ -82,8 +82,8 @@ class KitsuLibrary(AssetLibraryAdapter):
|
|||
description=data['description'],
|
||||
tags=[],
|
||||
type=self.data_type,
|
||||
image=str(self.image_template.format(name=asset_name)),
|
||||
video=str(self.video_template.format(name=asset_name)),
|
||||
image=str(self.template_image.format(name=asset_name)),
|
||||
video=str(self.template_video.format(name=asset_name)),
|
||||
name=data['name'])
|
||||
]
|
||||
)
|
||||
|
@ -98,17 +98,12 @@ class KitsuLibrary(AssetLibraryAdapter):
|
|||
def get_preview(self, asset_data):
|
||||
|
||||
name = asset_data['name']
|
||||
preview = (f / image_template.format(name=name)).resolve()
|
||||
preview = (f / template_image.format(name=name)).resolve()
|
||||
if not preview.exists():
|
||||
preview_blend_file(f, preview)
|
||||
|
||||
return preview
|
||||
|
||||
def conform(self, directory, templates):
|
||||
"""Split each assets per blend and externalize preview"""
|
||||
|
||||
print(f'Conforming {self.library.name} to {directory}')
|
||||
|
||||
|
||||
def fetch(self):
|
||||
"""Gather in a list all assets found in the folder"""
|
||||
|
|
|
@ -55,8 +55,8 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
metadata=dict(asset.asset_data),
|
||||
tags=asset.asset_data.tags.keys(),
|
||||
type=self.data_type,
|
||||
image=str(self.image_template.format(name=asset_name)),
|
||||
video=str(self.video_template.format(name=asset_name)),
|
||||
image=str(self.template_image.format(name=asset_name)),
|
||||
video=str(self.template_video.format(name=asset_name)),
|
||||
name=asset.name)
|
||||
)
|
||||
|
||||
|
@ -178,7 +178,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
asset.asset_mark()
|
||||
|
||||
# Load external preview if exists
|
||||
#image_template = Template(asset_data['preview'])
|
||||
#template_image = Template(asset_data['preview'])
|
||||
image_path = Path(asset_data['image'])
|
||||
if not image_path.is_absolute():
|
||||
image_path = Path(asset_data['filepath'], image_path)
|
||||
|
@ -242,7 +242,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
def get_preview(self, asset_data):
|
||||
|
||||
name = asset_data['name']
|
||||
preview = (f / image_template.format(name=name)).resolve()
|
||||
preview = (f / template_image.format(name=name)).resolve()
|
||||
if not preview.exists():
|
||||
preview_blend_file(f, preview)
|
||||
|
||||
|
@ -264,8 +264,8 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
catalog_ids = {v['id']: {'path': k, 'name': v['name']} for k,v in catalog_data.items()}
|
||||
directory = Path(directory).resolve()
|
||||
|
||||
image_template = templates.get('image') or self.image_template
|
||||
video_template = templates.get('video') or self.video_template
|
||||
template_image = templates.get('image') or self.template_image
|
||||
template_video = templates.get('video') or self.template_video
|
||||
|
||||
# Get list of all modifications
|
||||
for blend_file in self._find_blend_files():
|
||||
|
@ -295,12 +295,12 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
asset_path = self.get_asset_path(name=asset.name, catalog=catalog_path, directory=directory)
|
||||
asset_description = self.get_asset_description(asset, catalog=catalog_path, modified=modified)
|
||||
|
||||
self.write_asset_description(asset_description, asset_path)
|
||||
self.write_description_file(asset_description, asset_path)
|
||||
#Write blend file containing only one asset
|
||||
self.write_asset(asset=asset, asset_path=asset_path)
|
||||
|
||||
# Copy image if source image found else write the asset preview
|
||||
src_image_path = self.get_path('image', name=asset.name, asset_path=blend_file, template=image_template)
|
||||
src_image_path = self.get_path('image', name=asset.name, asset_path=blend_file, template=template_image)
|
||||
dst_image_path = self.get_path('image', name=asset.name, asset_path=asset_path)
|
||||
|
||||
if src_image_path.exists():
|
||||
|
@ -309,7 +309,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
self.write_preview(asset.preview, dst_image_path)
|
||||
|
||||
# Copy video if source video found
|
||||
src_video_path = self.get_path('video', name=asset.name, asset_path=blend_file, template=video_template)
|
||||
src_video_path = self.get_path('video', name=asset.name, asset_path=blend_file, template=template_video)
|
||||
|
||||
#print('src_video_path', src_video_path)
|
||||
if src_video_path.exists():
|
||||
|
@ -364,7 +364,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
if not field_data:
|
||||
raise Exception()
|
||||
|
||||
#asset_data = (blend_file / prefs.asset_description_template.format(name=name)).resolve()
|
||||
#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 = [c.replace('_', ' ').title() for c in catalogs]
|
||||
|
@ -387,7 +387,7 @@ class ScanFolderLibrary(AssetLibraryAdapter):
|
|||
continue
|
||||
|
||||
#First Check if there is a asset_data .json
|
||||
asset_description = self.read_asset_description(blend_file)
|
||||
asset_description = self.read_asset_description_file(blend_file)
|
||||
|
||||
if not asset_description:
|
||||
# Scan the blend file for assets inside and write a custom asset description for info found
|
||||
|
|
Binary file not shown.
|
@ -332,6 +332,9 @@ def load_datablocks(src, names=None, type='objects', link=True, expr=None) -> li
|
|||
return_list = not isinstance(names, str)
|
||||
names = names or []
|
||||
|
||||
if type.isupper():
|
||||
type = f'{type.lower()}s'
|
||||
|
||||
if not isinstance(names, (list, tuple)):
|
||||
names = [names]
|
||||
|
||||
|
|
|
@ -13,6 +13,17 @@ import importlib
|
|||
import sys
|
||||
import shutil
|
||||
|
||||
import contextlib
|
||||
|
||||
@contextlib.contextmanager
|
||||
def cd(path):
|
||||
"""Changes working directory and returns to previous on exit."""
|
||||
prev_cwd = Path.cwd()
|
||||
os.chdir(path)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(prev_cwd)
|
||||
|
||||
def install_module(module_name, package_name=None):
|
||||
'''Install a python module with pip or return it if already installed'''
|
||||
|
|
|
@ -181,6 +181,7 @@ def get_asset_source(replace_local=False):
|
|||
|
||||
return source_path
|
||||
|
||||
'''
|
||||
def get_catalog_path(filepath=None):
|
||||
filepath = filepath or bpy.data.filepath
|
||||
filepath = Path(filepath)
|
||||
|
@ -195,7 +196,7 @@ def get_catalog_path(filepath=None):
|
|||
catalog.touch(exist_ok=False)
|
||||
|
||||
return catalog
|
||||
|
||||
'''
|
||||
|
||||
# def read_catalog(path, key='path'):
|
||||
# cat_data = {}
|
||||
|
@ -219,7 +220,7 @@ def get_catalog_path(filepath=None):
|
|||
# cat_data[cat_name] = {'id':cat_id, 'path':cat_path}
|
||||
|
||||
# return cat_data
|
||||
|
||||
"""
|
||||
def read_catalog(path):
|
||||
cat_data = {}
|
||||
|
||||
|
@ -299,6 +300,7 @@ def create_catalog_file(json_path : str|Path, keep_existing_category : bool = Tr
|
|||
print(f'Catalog saved at: {catalog_path}')
|
||||
|
||||
return
|
||||
"""
|
||||
|
||||
def clear_env_libraries():
|
||||
print('clear_env_libraries')
|
||||
|
|
|
@ -54,14 +54,12 @@ class Template:
|
|||
|
||||
def format(self, data=None, **kargs):
|
||||
|
||||
#print('format', self.template, data, kargs)
|
||||
|
||||
data = {**(data or {}), **kargs}
|
||||
|
||||
try:
|
||||
path = self.template.format(**data)
|
||||
except KeyError:
|
||||
print(f'Cannot format {self.template} with {data}')
|
||||
except KeyError as e:
|
||||
print(f'Cannot format {self.template} with {data}, field {e} is missing')
|
||||
return
|
||||
|
||||
path = os.path.expandvars(path)
|
||||
|
|
|
@ -13,4 +13,5 @@ ASSETLIB_FILENAME = "blender_assets.libs.json"
|
|||
MODULE_DIR = Path(__file__).parent
|
||||
RESOURCES_DIR = MODULE_DIR / 'resources'
|
||||
ADAPTER_DIR = MODULE_DIR / 'adapters'
|
||||
ADAPTERS = []
|
||||
ADAPTERS = []
|
||||
PREVIEW_ASSETS_SCRIPT = MODULE_DIR / 'common' / 'preview_assets.py'
|
||||
|
|
|
@ -17,7 +17,7 @@ command, write_catalog)
|
|||
|
||||
|
||||
@command
|
||||
def bundle_library(source_directory, bundle_directory, asset_description_template, thumbnail_template,
|
||||
def bundle_library(source_directory, bundle_directory, template_description, thumbnail_template,
|
||||
template=None, data_file=None):
|
||||
|
||||
field_pattern = r'{(\w+)}'
|
||||
|
@ -38,7 +38,7 @@ def bundle_library(source_directory, bundle_directory, asset_description_templat
|
|||
|
||||
name = field_data.get('name', f.stem)
|
||||
thumbnail = (f / thumbnail_template.format(name=name)).resolve()
|
||||
asset_data = (f / asset_description_template.format(name=name)).resolve()
|
||||
asset_data = (f / template_description.format(name=name)).resolve()
|
||||
|
||||
catalogs = sorted([v for k,v in sorted(field_data.items()) if k.isdigit()])
|
||||
catalogs = [c.replace('_', ' ').title() for c in catalogs]
|
||||
|
@ -163,7 +163,7 @@ if __name__ == '__main__' :
|
|||
bundle_library(
|
||||
source_directory=args.source_directory,
|
||||
bundle_directory=args.bundle_directory,
|
||||
asset_description_template=args.asset_description_template,
|
||||
template_description=args.template_description,
|
||||
thumbnail_template=args.thumbnail_template,
|
||||
template=args.template,
|
||||
data_file=args.data_file)
|
||||
|
|
77
operators.py
77
operators.py
|
@ -112,8 +112,8 @@ class ASSETLIB_OT_edit_data(Operator):
|
|||
new_video_path = lib.adapter.get_path('video', new_name, new_asset_path)
|
||||
self.old_video_path.rename(new_video_path)
|
||||
|
||||
if self.old_asset_description_path.exists():
|
||||
self.old_asset_description_path.unlink()
|
||||
if self.old_description_path.exists():
|
||||
self.old_description_path.unlink()
|
||||
|
||||
new_asset_description = lib.adapter.get_asset_description(
|
||||
asset=self.asset,
|
||||
|
@ -121,7 +121,7 @@ class ASSETLIB_OT_edit_data(Operator):
|
|||
modified=time.time_ns()
|
||||
)
|
||||
|
||||
lib.adapter.write_asset_description(new_asset_description, new_asset_path)
|
||||
lib.adapter.write_description_file(new_asset_description, new_asset_path)
|
||||
|
||||
if not list(self.old_asset_path.parent.iterdir()):
|
||||
self.old_asset_path.parent.rmdir()
|
||||
|
@ -187,9 +187,9 @@ class ASSETLIB_OT_edit_data(Operator):
|
|||
self.old_image_path = lib.adapter.get_path('image', self.old_asset_name, self.old_asset_path)
|
||||
self.old_video_path = lib.adapter.get_path('video', self.old_asset_name, self.old_asset_path)
|
||||
|
||||
self.old_asset_description_path = lib.adapter.get_asset_description_path(self.old_asset_path)
|
||||
self.old_description_path = lib.adapter.get_description_path(self.old_asset_path)
|
||||
|
||||
self.old_asset_description = lib.adapter.read_asset_description(self.old_asset_path)
|
||||
self.old_asset_description = lib.adapter.read_asset_description_file(self.old_asset_path)
|
||||
self.old_asset_description = lib.adapter.norm_asset_datas([self.old_asset_description])[0]
|
||||
|
||||
|
||||
|
@ -408,8 +408,8 @@ class ASSETLIB_OT_conform_library(Operator):
|
|||
bl_description = "Split each assets per blend and externalize preview"
|
||||
|
||||
name : StringProperty()
|
||||
image_template : StringProperty()
|
||||
video_template : StringProperty()
|
||||
template_image : StringProperty()
|
||||
template_video : StringProperty()
|
||||
directory : StringProperty(subtype='DIR_PATH', name='Filepath')
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
|
@ -419,13 +419,13 @@ class ASSETLIB_OT_conform_library(Operator):
|
|||
#lib.adapter.conform(self.directory)
|
||||
|
||||
templates = {}
|
||||
if self.image_template:
|
||||
templates['image'] = self.image_template
|
||||
if self.video_template:
|
||||
templates['video'] = self.video_template
|
||||
if self.template_image:
|
||||
templates['image'] = self.template_image
|
||||
if self.template_video:
|
||||
templates['video'] = self.template_video
|
||||
|
||||
|
||||
script_path = Path(gettempdir()) / 'bundle_library.py'
|
||||
script_path = Path(bpy.app.tempdir) / 'bundle_library.py'
|
||||
script_code = dedent(f"""
|
||||
import bpy
|
||||
prefs = bpy.context.preferences.addons["asset_library"].preferences
|
||||
|
@ -447,6 +447,58 @@ class ASSETLIB_OT_conform_library(Operator):
|
|||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
class ASSETLIB_OT_generate_previews(Operator):
|
||||
bl_idname = "assetlib.generate_previews"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_label = "Generate Previews"
|
||||
bl_description = "Generate and write the image for assets"
|
||||
|
||||
diff : StringProperty()
|
||||
preview_blend : StringProperty()
|
||||
name : StringProperty()
|
||||
blocking : BoolProperty(default=True)
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
prefs = get_addon_prefs()
|
||||
lib = prefs.libraries.get(self.name)
|
||||
# self.write_file(self.diff_file, self.diff)
|
||||
|
||||
# preview_assets = [(a.asset_data['filepath'], self.data_types, a.name) for a in assets]
|
||||
|
||||
# self.preview_assets_file.write_text(json.dumps(preview_assets), encoding='utf-8')
|
||||
|
||||
# cmd = [
|
||||
# bpy.app.binary_path, '-b', '--use-system-env',
|
||||
# '--python', str(PREVIEW_ASSETS_SCRIPT), '--',
|
||||
# '--preview-blend', str(self.preview_blend),
|
||||
# '--preview-assets-file', str(self.preview_assets_file)
|
||||
# ]
|
||||
# subprocess.call(cmd)
|
||||
preview_blend = self.preview_blend or lib.adapter.preview_blend
|
||||
|
||||
script_path = Path(bpy.app.tempdir) / 'generate_previews.py'
|
||||
script_code = dedent(f"""
|
||||
import bpy
|
||||
prefs = bpy.context.preferences.addons["asset_library"].preferences
|
||||
lib = prefs.env_libraries.add()
|
||||
lib.set_dict({lib.to_dict()})
|
||||
|
||||
bpy.ops.wm.open_mainfile(filepath='{preview_blend}', load_ui=True)
|
||||
lib.conform.adapter.generate_previews()
|
||||
""")
|
||||
|
||||
script_path.write_text(script_code)
|
||||
|
||||
cmd = get_bl_cmd(script=str(script_path), background=True)
|
||||
|
||||
if self.blocking:
|
||||
subprocess.call(cmd)
|
||||
else:
|
||||
subprocess.Popen(cmd)
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class ASSETLIB_OT_play_preview(Operator):
|
||||
bl_idname = "assetlib.play_preview"
|
||||
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
||||
|
@ -553,6 +605,7 @@ classes = (
|
|||
ASSETLIB_OT_add_user_library,
|
||||
ASSETLIB_OT_remove_user_library,
|
||||
ASSETLIB_OT_diff,
|
||||
ASSETLIB_OT_generate_previews,
|
||||
ASSETLIB_OT_bundle_library,
|
||||
ASSETLIB_OT_clear_asset,
|
||||
ASSETLIB_OT_edit_data,
|
||||
|
|
69
prefs.py
69
prefs.py
|
@ -12,7 +12,7 @@ from asset_library.constants import (DATA_TYPES, DATA_TYPE_ITEMS,
|
|||
|
||||
from asset_library.common.file_utils import import_module_from_path, norm_str
|
||||
from asset_library.common.bl_utils import get_addon_prefs
|
||||
from asset_library.common.functions import get_catalog_path
|
||||
#from asset_library.common.functions import get_catalog_path
|
||||
|
||||
from pathlib import Path
|
||||
import importlib
|
||||
|
@ -88,14 +88,16 @@ class ConformAssetLibrary(PropertyGroup):
|
|||
adapters : bpy.props.PointerProperty(type=AssetLibraryAdapters)
|
||||
adapter_name : EnumProperty(items=get_adapter_items)
|
||||
directory : StringProperty(
|
||||
name="Destination Directory",
|
||||
name="Target Directory",
|
||||
subtype='DIR_PATH',
|
||||
default=''
|
||||
)
|
||||
image_template : StringProperty()
|
||||
video_template : StringProperty()
|
||||
|
||||
externalize_data: BoolProperty(default=False, name='Externalize Data')
|
||||
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')
|
||||
|
||||
#externalize_data: BoolProperty(default=False, name='Externalize Data')
|
||||
blend_depth: IntProperty(default=1, name='Blend Depth')
|
||||
|
||||
@property
|
||||
|
@ -228,23 +230,23 @@ class AssetLibrary(PropertyGroup):
|
|||
return self.name
|
||||
|
||||
@property
|
||||
def image_template(self):
|
||||
def template_image(self):
|
||||
prefs = get_addon_prefs()
|
||||
return prefs.image_template
|
||||
return prefs.template_image
|
||||
|
||||
@property
|
||||
def video_template(self):
|
||||
def template_video(self):
|
||||
prefs = get_addon_prefs()
|
||||
return prefs.video_template
|
||||
return prefs.template_video
|
||||
|
||||
@property
|
||||
def asset_description_template(self):
|
||||
def template_description(self):
|
||||
prefs = get_addon_prefs()
|
||||
return prefs.asset_description_template
|
||||
return prefs.template_description
|
||||
|
||||
@property
|
||||
def catalog_path(self):
|
||||
return get_catalog_path(self.library_path)
|
||||
#@property
|
||||
#def catalog_path(self):
|
||||
# return get_catalog_path(self.library_path)
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
|
@ -376,7 +378,7 @@ class AssetLibrary(PropertyGroup):
|
|||
if not self.use:
|
||||
if all(not l.use for l in self.merge_libraries):
|
||||
self.clear_library_path()
|
||||
return
|
||||
return
|
||||
|
||||
# Create the Asset Library Path
|
||||
if not lib:
|
||||
|
@ -470,6 +472,10 @@ class AssetLibrary(PropertyGroup):
|
|||
op.name = self.name
|
||||
op.conform = True
|
||||
|
||||
op = subrow.operator('assetlib.generate_previews', text='', icon='SEQ_PREVIEW')#, icon='MOD_BUILD'
|
||||
op.name = self.name
|
||||
#op.conform = True
|
||||
|
||||
op = subrow.operator('assetlib.bundle', text='', icon='MOD_BUILD')#, icon='MOD_BUILD'
|
||||
op.name = self.name
|
||||
op.directory = self.conform.directory
|
||||
|
@ -479,17 +485,22 @@ class AssetLibrary(PropertyGroup):
|
|||
#subrow.separator(factor=3)
|
||||
|
||||
if self.expand_extra and self.conform.adapter:
|
||||
col.separator()
|
||||
self.conform.adapter.draw_prefs(col)
|
||||
|
||||
col.separator()
|
||||
col.separator()
|
||||
#row = layout.row(align=True)
|
||||
#row.label(text='Conform Library')
|
||||
col.prop(self.conform, "directory")
|
||||
col.prop(self.conform, "blend_depth")
|
||||
col.prop(self.conform, "externalize_data")
|
||||
col.prop(self.conform, "image_template", text='Image Template')
|
||||
col.prop(self.conform, "video_template", text='Video Template')
|
||||
#col.prop(self.conform, "externalize_data")
|
||||
subcol = col.column(align=True)
|
||||
subcol.prop(self.conform, "template_description", text='Template Description', icon='COPY_ID')
|
||||
subcol.prop(self.conform, "template_image", text='Template Image', icon='COPY_ID')
|
||||
subcol.prop(self.conform, "template_video", text='Template Video', icon='COPY_ID')
|
||||
|
||||
col.separator()
|
||||
self.conform.adapter.draw_prefs(col)
|
||||
|
||||
|
||||
col.separator()
|
||||
|
||||
|
@ -651,10 +662,10 @@ class AssetLibraryPrefs(AddonPreferences):
|
|||
update=update_all_library_path
|
||||
)
|
||||
|
||||
use_single_path : BoolProperty(default=True)
|
||||
asset_description_template : StringProperty(default='../{name}_asset_description.json')
|
||||
image_template : StringProperty(default='../{name}_image.png')
|
||||
video_template : StringProperty(default='../{name}_video.mov')
|
||||
#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(
|
||||
name="Config Path",
|
||||
|
@ -745,16 +756,16 @@ class AssetLibraryPrefs(AddonPreferences):
|
|||
|
||||
col.separator()
|
||||
|
||||
col.prop(self, 'asset_description_template', text='Asset Description Template', icon='COPY_ID')
|
||||
#col.prop(self, 'template_description', text='Asset Description Template', icon='COPY_ID')
|
||||
|
||||
col.separator()
|
||||
#col.separator()
|
||||
|
||||
col.prop(self, 'image_template', text='Image Template', icon='COPY_ID')
|
||||
#col.prop(self, 'template_image', text='Template Image', icon='COPY_ID')
|
||||
col.prop(self, 'image_player', text='Image Player') #icon='OUTLINER_OB_IMAGE'
|
||||
|
||||
col.separator()
|
||||
#col.separator()
|
||||
|
||||
col.prop(self, 'video_template', text='Video Template', icon='COPY_ID')
|
||||
#col.prop(self, 'template_video', text='Template Video', icon='COPY_ID')
|
||||
col.prop(self, 'video_player', text='Video Player') #icon='FILE_MOVIE'
|
||||
|
||||
col.separator()
|
||||
|
|
Loading…
Reference in New Issue