From fc405797d90b6ca9c66379663cf82a898449c408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cchristopheseux=E2=80=9D?= <“seuxchristophe@hotmail.fr”> Date: Sun, 25 Dec 2022 02:54:50 +0100 Subject: [PATCH] start kitsu adapter --- action/clear_asset.py | 2 +- action/rename_pose.py | 2 +- action/render_preview.py | 2 +- adapters/adapter.py | 40 ++++++++++++++++++----- adapters/kitsu.py | 14 ++++---- common/bl_utils.py | 4 ++- constants.py | 9 +++--- operators.py | 19 ++++++++--- prefs.py | 70 ++++++++++++++++++++++++++++------------ 9 files changed, 113 insertions(+), 49 deletions(-) diff --git a/action/clear_asset.py b/action/clear_asset.py index b01947f..72b4e38 100644 --- a/action/clear_asset.py +++ b/action/clear_asset.py @@ -5,7 +5,7 @@ import json import sys from pathlib import Path -sys.path.append(Path(__file__).parents[3]) +#sys.path.append(str(Path(__file__).parents[3])) from asset_library.common.bl_utils import ( get_preview, ) diff --git a/action/rename_pose.py b/action/rename_pose.py index 9ef461e..3c9f722 100644 --- a/action/rename_pose.py +++ b/action/rename_pose.py @@ -6,7 +6,7 @@ import re import sys from pathlib import Path -sys.path.append(Path(__file__).parents[3]) +#sys.path.append(str(Path(__file__).parents[3])) from asset_library.common.bl_utils import ( get_preview, ) diff --git a/action/render_preview.py b/action/render_preview.py index 7edec25..c5436d7 100644 --- a/action/render_preview.py +++ b/action/render_preview.py @@ -2,7 +2,7 @@ import sys from pathlib import Path -sys.path.append(str(Path(__file__).parents[3])) +#sys.path.append(str(Path(__file__).parents[3])) from asset_library.action.concat_preview import mosaic_export from asset_library.common.file_utils import open_file diff --git a/adapters/adapter.py b/adapters/adapter.py index aae3d97..c4e4a67 100644 --- a/adapters/adapter.py +++ b/adapters/adapter.py @@ -16,6 +16,8 @@ import shutil import os import json import uuid +import time +from functools import partial class AssetLibraryAdapter(PropertyGroup): @@ -59,8 +61,20 @@ class AssetLibraryAdapter(PropertyGroup): def data_types(self): return self.library.data_types + @property + def is_conform(self): + prefs = self.addon_prefs + for lib in prefs.libraries: + if lib.adapter == self: + return False + if lib.conform.adapter == self: + return True + @property def blend_depth(self): + if self.is_conform: + return self.library.conform.blend_depth + return self.library.blend_depth @property @@ -331,19 +345,28 @@ class AssetLibraryAdapter(PropertyGroup): return #Creating the preview for collection, object or material - src_asset = self.load_datablocks(asset_data['filepath'], names=asset_data['name'], link=True, type=self.data_types) + 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) #Transfering pixels between previews - pixels = [0] * (128*128*4) + 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) - getattr(bpy.data, self.data_types).remove(src_asset) + #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) def set_asset_catalog(self, asset, asset_data, catalog_data): @@ -408,7 +431,7 @@ class AssetLibraryAdapter(PropertyGroup): else: cache_diff.sort(key=self.group_key) groups = groupby(cache_diff, key=self.group_key) - + total_assets = len(cache_diff) print(f'total_assets={total_assets}') @@ -474,14 +497,13 @@ class AssetLibraryAdapter(PropertyGroup): 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) + #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): """ Return a new flat list of asset data the filepath keys are merge with the assets keys""" @@ -510,6 +532,8 @@ class AssetLibraryAdapter(PropertyGroup): new_cache = self.fetch() + #print(cache) + cache = {f"{a['filepath']}/{a['name']}": a for a in self.norm_cache(cache)} new_cache = {f"{a['filepath']}/{a['name']}" : a for a in self.norm_cache(new_cache)} diff --git a/adapters/kitsu.py b/adapters/kitsu.py index ef91844..f07e558 100644 --- a/adapters/kitsu.py +++ b/adapters/kitsu.py @@ -21,8 +21,6 @@ import urllib3 import traceback import time -gazu = install_module('gazu') - class KitsuLibrary(AssetLibraryAdapter): @@ -38,6 +36,7 @@ class KitsuLibrary(AssetLibraryAdapter): def connect(self, url=None, login=None, password=None): '''Connect to kitsu api using provided url, login and password''' + gazu = install_module('gazu') urllib3.disable_warnings() if not self.url: @@ -74,7 +73,7 @@ class KitsuLibrary(AssetLibraryAdapter): asset_name = self.norm_file_name(data['name']) asset_description = dict( - filepath='{source_directory}/' + asset_path.as_posix(), + filepath=asset_path.as_posix(), modified=modified, library_id=self.library.id, assets=[dict( @@ -91,10 +90,10 @@ class KitsuLibrary(AssetLibraryAdapter): return asset_description - def bundle(self, cache_diff=None): - """Group all asset in one or multiple blends for the asset browser""" + # def bundle(self, cache_diff=None): + # """Group all asset in one or multiple blends for the asset browser""" - return super().bundle(cache_diff=cache_diff) + # return super().bundle(cache_diff=cache_diff) def get_preview(self, asset_data): @@ -116,6 +115,7 @@ class KitsuLibrary(AssetLibraryAdapter): print(f'Fetch Assets for {self.library.name}') + gazu = install_module('gazu') self.connect() template_file = Template(self.template_file) @@ -126,7 +126,7 @@ class KitsuLibrary(AssetLibraryAdapter): entity_types_ids = {e['id']: e['name'] for e in entity_types} new_cache = [] - for asset_data in gazu.asset.all_assets_for_project(project): + for asset_data in gazu.asset.all_assets_for_project(project)[:10]: asset_data['entity_type_name'] = entity_types_ids[asset_data.pop('entity_type_id')] asset_name = asset_data['name'] diff --git a/common/bl_utils.py b/common/bl_utils.py index b3abdbe..edac2c5 100644 --- a/common/bl_utils.py +++ b/common/bl_utils.py @@ -184,12 +184,14 @@ def get_bl_cmd(blender=None, background=False, focus=True, blendfile=None, scrip cmd += ['--no-window-focus'] cmd += ['--window-geometry', '5000', '0', '10', '10'] + cmd += ['--python-use-system-env'] + if blendfile: cmd += [str(blendfile)] if script: cmd += ['--python', str(script)] - + if kargs: cmd += ['--'] for k, v in kargs.items(): diff --git a/constants.py b/constants.py index 93ffdb5..f00f20e 100644 --- a/constants.py +++ b/constants.py @@ -2,9 +2,9 @@ from pathlib import Path DATA_TYPE_ITEMS = [ - ("ACTION", "Action", "", "ACTION", 1), - ("COLLECTION", "Collection", "", "OUTLINER_OB_GROUP_INSTANCE", 2), - ("FILE", "File", "", "FILE", 3) + ("ACTION", "Action", "", "ACTION", 0), + ("COLLECTION", "Collection", "", "OUTLINER_OB_GROUP_INSTANCE", 1), + ("FILE", "File", "", "FILE", 2) ] DATA_TYPES = [i[0] for i in DATA_TYPE_ITEMS] ICONS = {identifier: icon for identifier, name, description, icon, number in DATA_TYPE_ITEMS} @@ -12,4 +12,5 @@ ICONS = {identifier: icon for identifier, name, description, icon, number in DAT ASSETLIB_FILENAME = "blender_assets.libs.json" MODULE_DIR = Path(__file__).parent RESOURCES_DIR = MODULE_DIR / 'resources' -ADAPTER_DIR = MODULE_DIR / 'adapters' \ No newline at end of file +ADAPTER_DIR = MODULE_DIR / 'adapters' +ADAPTERS = [] \ No newline at end of file diff --git a/operators.py b/operators.py index aeeed30..2fb20a1 100644 --- a/operators.py +++ b/operators.py @@ -302,7 +302,7 @@ class ASSETLIB_OT_bundle_library(Operator): blocking : BoolProperty(default=False) mode : EnumProperty(items=[(i.replace(' ', '_').upper(), i, '') for i in ('None', 'All', 'Auto Bundle')], default='NONE') directory : StringProperty(subtype='DIR_PATH') - + conform : BoolProperty(default=False) #def refresh(self): # for area in suitable_areas(bpy.context.screen): # bpy.ops.asset.library_refresh({"area": area, 'region': area.regions[3]}) @@ -318,13 +318,19 @@ class ASSETLIB_OT_bundle_library(Operator): if self.mode == 'ALL': libs += prefs.libraries.values() elif self.mode == 'AUTO_BUNDLE': - libs += [l for l in prefs.libraries if l.auto_bundle] + libs += [l for l in prefs.libraries if l.auto_bundle] + + if not libs: + return {"CANCELLED"} lib_datas = [l.to_dict() for l in libs] print(f'Bundle Libraries: {[l.name for l in libs]}') - script_path = Path(gettempdir()) / 'bundle_library.py' + adapter = "lib.adapter" + if self.conform: + adapter = "lib.conform.adapter" + script_code = dedent(f""" import bpy prefs = bpy.context.preferences.addons["asset_library"].preferences @@ -332,12 +338,15 @@ class ASSETLIB_OT_bundle_library(Operator): for lib_data in {lib_datas}: lib = prefs.env_libraries.add() lib.set_dict(lib_data) - lib.adapter.bundle(cache_diff='{self.diff}') + {adapter}.bundle(cache_diff='{self.diff}') + + bpy.ops.wm.quit_blender() """) + script_path = Path(bpy.app.tempdir) / 'bundle_library.py' script_path.write_text(script_code) - #print(script_code) + print(script_code) #raise Exception() diff --git a/prefs.py b/prefs.py index 0a4e901..f806d1f 100644 --- a/prefs.py +++ b/prefs.py @@ -8,7 +8,7 @@ from bpy.props import (BoolProperty, StringProperty, CollectionProperty, EnumProperty, IntProperty) from asset_library.constants import (DATA_TYPES, DATA_TYPE_ITEMS, - ICONS, RESOURCES_DIR, ADAPTER_DIR) + ICONS, RESOURCES_DIR, ADAPTER_DIR, ADAPTERS) from asset_library.common.file_utils import import_module_from_path, norm_str from asset_library.common.bl_utils import get_addon_prefs @@ -19,8 +19,6 @@ import importlib import inspect -ADAPTERS = [] - def update_library_config(self, context): print('update_library_config not yet implemented') @@ -72,11 +70,11 @@ def get_library_items(self, context): return items def get_store_library_items(self, context): - prefs = get_addon_prefs() + #prefs = get_addon_prefs() - libraries = [l for l in prefs.libraries if l.merge_library == self.name] + #libraries = [l for l in prefs.libraries if l.merge_library == self.name] - return [(l.name, l.name, "", i) for i, l in enumerate([self] + libraries)] + return [(l.name, l.name, "", i) for i, l in enumerate([self] + self.merge_libraries)] class AssetLibraryAdapters(PropertyGroup): @@ -108,6 +106,16 @@ class ConformAssetLibrary(PropertyGroup): return getattr(self.adapters, name) + def to_dict(self): + data = {p: getattr(self, p) for p in self.bl_rna.properties.keys() if p !='rna_type'} + + data['adapter'] = self.adapter.to_dict() + data['adapter']['name'] = data.pop('adapter_name') + + del data['adapters'] + + return data + class AssetLibrary(PropertyGroup): name : StringProperty(name='Name', default='Action Library', update=update_library_path) @@ -115,7 +123,8 @@ class AssetLibrary(PropertyGroup): auto_bundle : BoolProperty(name='Auto Bundle', default=True) expand : BoolProperty(name='Expand', default=False) use : BoolProperty(name='Use', default=True, update=update_library_path) - data_type : EnumProperty(name='Type', items=DATA_TYPE_ITEMS, default='ACTION') + data_type : EnumProperty(name='Type', items=DATA_TYPE_ITEMS, default='COLLECTION') + bundle_directory : StringProperty( name="Bundle Directory", @@ -268,7 +277,9 @@ class AssetLibrary(PropertyGroup): def set_dict(self, data, obj=None): """"Recursive method to set all attribute from a dict to this instance""" - obj = obj or self + + if obj is None: + obj = self # Make shure the input dict is not modidied data = data.copy() @@ -277,11 +288,11 @@ class AssetLibrary(PropertyGroup): for key, value in data.items(): if isinstance(value, dict): - #print('Nested value', key) if 'name' in value: setattr(obj, f'{key}_name', value.pop('name')) + print('Nested value', getattr(obj, key)) self.set_dict(value, obj=getattr(obj, key)) elif key in obj.bl_rna.properties.keys(): @@ -296,7 +307,9 @@ class AssetLibrary(PropertyGroup): value = os.path.expandvars(value) value = os.path.expanduser(value) - obj[key] = value + #print('set attr', key, value) + setattr(obj, key, value) + #obj[key] = value else: print(f'Prop {key} of {obj} not exist') @@ -328,9 +341,13 @@ class AssetLibrary(PropertyGroup): def to_dict(self): data = {p: getattr(self, p) for p in self.bl_rna.properties.keys() if p !='rna_type'} - data['options'] = self.adapter.to_dict() - data['adapter'] = data.pop('adapter_name') + data['adapter'] = self.adapter.to_dict() + #data['adapter'] = data.pop('adapter_name') + data['adapter']['name'] = data.pop('adapter_name') del data['adapters'] + + data['conform'] = self.conform.to_dict() + return data def set_library_path(self): @@ -456,6 +473,8 @@ class AssetLibrary(PropertyGroup): op = subrow.operator('assetlib.bundle', text='', icon='MOD_BUILD')#, icon='MOD_BUILD' op.name = self.name op.directory = self.conform.directory + op.conform = True + subrow.label(icon='BLANK1') #subrow.separator(factor=3) @@ -482,6 +501,9 @@ class AssetLibrary(PropertyGroup): box = layout.box() row = box.row(align=True) + #row.use_property_split = False + + #row.alignment = 'LEFT' icon = "DISCLOSURE_TRI_DOWN" if self.expand else "DISCLOSURE_TRI_RIGHT" row.prop(self, 'expand', icon=icon, emboss=False, text='') @@ -498,7 +520,11 @@ class AssetLibrary(PropertyGroup): else: row.prop(self, 'use', text='') row.label(icon=ICONS[self.data_type]) - row.label(text=self.name) + #row.label(text=self.name) + subrow = row.row(align=True) + subrow.alignment = 'LEFT' + subrow.prop(self, 'expand', emboss=False, text=self.name) + #row.separator_spacer() self.draw_operators(row) @@ -601,6 +627,8 @@ class Collections: class AssetLibraryPrefs(AddonPreferences): bl_idname = __package__ + adapters = [] + #action : bpy.props.PointerProperty(type=AssetLibraryPath) #asset : bpy.props.PointerProperty(type=AssetLibraryPath) #adapters = {} @@ -656,13 +684,13 @@ class AssetLibraryPrefs(AddonPreferences): if adapter_file.stem.startswith('_'): continue - print(adapter_file) + #print(adapter_file) for name, obj in inspect.getmembers(mod): if not inspect.isclass(obj): continue - print(obj.__bases__) + #print(obj.__bases__) if not AssetLibraryAdapter in obj.__mro__: continue @@ -742,12 +770,12 @@ class AssetLibraryPrefs(AddonPreferences): row.operator("assetlib.add_user_library", icon="ADD", text='', emboss=False) -classes = ( +classes = [ AssetLibraryAdapters, ConformAssetLibrary, AssetLibrary, AssetLibraryPrefs, -) +] def register(): for cls in classes: @@ -758,20 +786,20 @@ def register(): # Read Env and override preferences bundle_dir = os.getenv('ASSETLIB_BUNDLE_DIR') if bundle_dir: - prefs.bundle_directory = os.path.expandvars(bundle_dir) + prefs['bundle_directory'] = os.path.expandvars(bundle_dir) config_dir = os.getenv('ASSETLIB_CONFIG_DIR') if config_dir: - prefs.config_directory = os.path.expandvars(config_dir) + prefs['config_directory'] = os.path.expandvars(config_dir) adapter_dir = os.getenv('ASSETLIB_ADAPTER_DIR') if adapter_dir: - prefs.adapter_directory = os.path.expandvars(adapter_dir) + prefs['adapter_directory'] = os.path.expandvars(adapter_dir) prefs.load_adapters() def unregister(): - for cls in reversed(list(classes) + ADAPTERS): + for cls in reversed(classes + ADAPTERS): bpy.utils.unregister_class(cls) ADAPTERS.clear() \ No newline at end of file