diff --git a/operators/operators.py b/operators/operators.py index 949da7c..1893eca 100644 --- a/operators/operators.py +++ b/operators/operators.py @@ -45,6 +45,31 @@ from vse_toolbox.sequencer_utils import ( from vse_toolbox.bl_utils import get_addon_prefs, get_scene_settings, get_strip_settings from vse_toolbox.file_utils import install_module, norm_name, norm_str +class VSETB_OT_tracker_connect(Operator): + bl_idname = "vse_toolbox.tracker_connect" + bl_label = "Connect to Tracker" + bl_description = "Connect to Tracker" + + @classmethod + def poll(cls, context): + prefs = get_addon_prefs() + if prefs.tracker: + + return True + + def execute(self, context): + prefs = get_addon_prefs() + settings = get_scene_settings() + try: + prefs.tracker.connect() + self.report({'INFO'}, f'Sucessfully login to {settings.tracker_name.title()}') + return {"FINISHED"} + except Exception as e: + print('e: ', e) + self.report({'ERROR'}, f'Cannot connect to tracker.') + return {"CANCELLED"} + + class VSETB_OT_export_csv(Operator): bl_idname = "sequencer.export_csv" bl_label = "Set Scene" @@ -106,32 +131,6 @@ class VSETB_OT_auto_select_files(Operator): return {'FINISHED'} -# class VSETB_OT_select_file(Operator): -# bl_idname = "import.select_file" -# bl_label = "Select File" -# bl_description = "Select Active as File" -# bl_options = {"REGISTER", "UNDO"} - -# type : StringProperty('') - -# @classmethod -# def poll(cls, context): -# return True - -# def execute(self, context): -# params = context.space_data.params - -# print(params.filename) -# if self.type == 'edit': -# bpy.ops.sequencer.import_files(edit=params.filename) -# elif self.type == 'movie': -# bpy.ops.sequencer.import_files(movie=params.filename) -# elif self.type == 'sound': -# bpy.ops.sequencer.import_files(sound=params.filename) - -# return {'FINISHED'} - - class VSETB_OT_import_files(Operator): bl_idname = "sequencer.import_files" bl_label = "Import" @@ -181,24 +180,18 @@ class VSETB_OT_import_files(Operator): sub = row.row(align=True) sub.active = self.import_edit sub.prop(self, 'edit') - # op = sub.operator('import.select_file', text="", icon='EYEDROPPER') - # op.type = 'edit' row = self.layout.row(heading="Import Movie", align=True) row.prop(self, 'import_movie') sub = row.row() sub.active = self.import_movie sub.prop(self, 'movie') - # op = sub.operator('import.select_file', text="", icon='EYEDROPPER') - # op.type = 'movie' row = self.layout.row(heading="Import Sound", align=True) row.prop(self, 'import_sound') sub = row.row() sub.active = self.import_sound sub.prop(self, 'sound') - # op = sub.operator('import.select_file', text="", icon='EYEDROPPER') - # op.type = 'sound' col = layout.column() col.separator() @@ -727,8 +720,8 @@ classes=( VSETB_OT_reload_addon, VSETB_OT_rename, VSETB_OT_render, - # VSETB_OT_select_file, VSETB_OT_set_scene, + VSETB_OT_tracker_connect, ) def register(): diff --git a/panels.py b/panels.py index 09643cc..4d4d950 100644 --- a/panels.py +++ b/panels.py @@ -176,8 +176,7 @@ class VSETB_PT_metadata(VSETB_main, Panel): return col = layout.column() - for key in strip_settings.metadata.keys(): - print('key: ', key) + for key in strip_settings.metadata.keys(): col.prop(strip_settings.metadata, key) classes=( diff --git a/preferences.py b/preferences.py index 8909b2e..98bfffa 100644 --- a/preferences.py +++ b/preferences.py @@ -120,6 +120,8 @@ class VSETB_Prefs(AddonPreferences): if self.expand_settings: box.prop(settings, 'tracker_name', text='Tracker') self.tracker.draw_prefs(box) + row = box.row() + row.operator("vse_toolbox.tracker_connect", text='Connect') classes=[ diff --git a/resources/trackers/tracker_test/trackertest.py b/resources/trackers/tracker_test/trackertest.py new file mode 100644 index 0000000..afa65c4 --- /dev/null +++ b/resources/trackers/tracker_test/trackertest.py @@ -0,0 +1,171 @@ + +import bpy +import os +import re +import urllib3 +import traceback +import time + +from bpy.props import PointerProperty, StringProperty +from pathlib import Path +from vse_toolbox.bl_utils import get_addon_prefs, get_scene_settings +from vse_toolbox.file_utils import install_module, norm_str +from vse_toolbox.resources.trackers.tracker import Tracker + +gazu = install_module('gazu') + +class TrackerTest(Tracker): + name = "TrackerTest" + + url: StringProperty() + login: StringProperty() + password: StringProperty(subtype='PASSWORD') + custom_field: StringProperty(subtype='PASSWORD') + + project_name = None + + def draw_prefs(self, layout): + layout.prop(self, 'url', text='Url') + layout.prop(self, 'login', text='Login') + layout.prop(self, 'password', text='Password') + layout.prop(self, 'custom_field', text='Password') + + def get_projects(self): + return gazu.project.all_open_projects() + + def get_episodes(self, project): + return gazu.shot.all_episodes_for_project(project) + + def get_episode(self, name): + return gazu.shot.get_episode_by_name(self.project, name) + + def get_asset_types(self, project): + asset_types = gazu.asset.all_asset_types_for_project(project) + return {t['id']:t['name'] for t in asset_types} + + def get_assets(self, project): + asset_types = self.get_asset_types(project) + assets = gazu.asset.all_assets_for_project(project) + + for asset in assets: + asset['asset_type'] = asset_types[asset['entity_type_id']] + + return assets + + def get_shots_metadata(self, project): + metadata = [] + for md in gazu.project.all_metadata_descriptors(project): + entity_type = md.get('entity_type') + field_name = md.get('field_name') + if entity_type and entity_type.lower() == 'shot' and field_name: + metadata.append(field_name) + + return metadata + + def download_preview(self, preview_id, filepath): + if isinstance(filepath, str): + filepath = Path(filepath) + + if filepath.exists(): + return + + filepath.parent.mkdir(parents=True, exist_ok=True) + gazu.files.download_preview_file_thumbnail(preview_id, filepath.as_posix()) + + def connect(self, url=None, login=None, password=None): + '''Connect to kitsu api using provided url, login and password''' + + urllib3.disable_warnings() + + if not self.url: + print(f'Kitsu Url: {self.url} is empty') + return + + url = self.url + if not url.endswith('/api'): + url += '/api' + + print(f'Info: Setting Host for kitsu {url}') + gazu.client.set_host(url) + + if not gazu.client.host_is_up(): + print('Error: Kitsu Host is down') + + try: + print(f'Info: Log in to kitsu as {self.login}') + res = gazu.log_in(self.login, self.password) + print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}') + return res['user'] + except Exception as e: + print(f'Error: {traceback.format_exc()}') + + def get_asset_path(self, name, catalog, directory=None): + directory = directory or self.source_directory + return Path(directory, self.get_asset_relative_path(name, catalog)) + + def get_asset_info(self, data, asset_path): + modified = time.time_ns() + catalog = data['entity_type_name'].title() + asset_path = self.prop_rel_path(asset_path, 'source_directory') + + asset_info = dict( + filepath=asset_path, + modified=modified, + library_id=self.library.id, + assets=[dict( + catalog=catalog, + metadata=data.get('data', {}), + description=data['description'], + tags=[], + type=self.data_type, + name=data['name']) + ] + ) + + return asset_info + + def fetch(self): + """Gather in a list all assets found in the folder""" + print(f'Fetch Assets for {self.library.name}') + + self.connect() + + template_file = Template(self.template_file) + template_name = Template(self.template_name) + + project = gazu.client.fetch_first('projects', {'name': self.project_name}) + entity_types = gazu.client.fetch_all('entity-types') + entity_types_ids = {e['id']: e['name'] for e in entity_types} + + cache = self.read_cache() + + 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_name = asset_data['name'] + + asset_field_data = dict(asset_name=asset_name, type=asset_data['entity_type_name'], source_directory=self.source_directory) + + try: + asset_field_data.update(template_name.parse(asset_name)) + except Exception: + print(f'Warning: Could not parse {asset_name} with template {template_name}') + + asset_path = template_file.find(asset_field_data) + if not asset_path: + print(f'Warning: Could not find file for {template_file.format(asset_field_data)}') + continue + + + asset_path = self.prop_rel_path(asset_path, 'source_directory') + asset_cache_data = dict( + catalog=asset_data['entity_type_name'].title(), + metadata=asset_data.get('data', {}), + description=asset_data['description'], + tags=[], + type=self.data_type, + name=asset_data['name'] + ) + + cache.add_asset_cache(asset_cache_data, filepath=asset_path) + + return cache \ No newline at end of file