Action Maya Convert 2016
unknown
python
4 years ago
9.4 kB
5
Indexable
# :coding: utf-8 import logging import os.path import threading import json import sys # noinspection DuplicatedCode PFX_LIB_DIRECTORY = os.path.abspath(os.environ.get('STUDIO_LIBRARY')) if PFX_LIB_DIRECTORY not in sys.path: sys.path.append(PFX_LIB_DIRECTORY) VENDOR_DIRECTORY = os.path.abspath(os.environ.get('STUDIO_VENDOR')) if VENDOR_DIRECTORY not in sys.path: sys.path.append(VENDOR_DIRECTORY) import ftrack_api # noqa: E402 from ftrack_action_handler.action import BaseAction # noqa: E402 from studio_library.helpers.ftrack_classes.FtrackSendMaya2016Constructor import FtrackSendMaya2016Constructor # noqa: E402 ENTITY_TYPES = {'AssetVersion': 'version.id', 'TypedContext': 'version.task_id', 'Component': 'id'} def asynchronous(fn): """Run *fn* asynchronously.""" def wrapper(*args, **kwargs): thread = threading.Thread(target=fn, args=args, kwargs=kwargs) thread.start() return wrapper # noinspection SpellCheckingInspection,DuplicatedCode def _get_components(session, entity_type, entity_id): components = session.query( 'select id, name, version, version.task, ' 'version.task.name, version.task.parent.name, version.task.parent.parent.name from Component ' 'where {arg} is {id} ' 'and name is scene'.format( arg=ENTITY_TYPES.get(entity_type, 'version.task_id'), id=entity_id)).all() task = components[0]['version']['task'] if components else None return task, components # noinspection PyBroadException def _update_job(job, description, session, status='running'): job['data'] = json.dumps({'description': description}) job['status'] = status try: session.commit() except Exception: session.rollback() raise else: return job # noinspection PyBroadException def _add_job_component(job, component_id, session): session.create( 'JobComponent', {'component_id': component_id, 'job_id': job['id']} ) try: session.commit() except Exception: session.rollback() # noinspection PyBroadException class ConvertToMaya2016Action(BaseAction): """Action to write note on multiple entities.""" identifier = 'convert-to-maya-2016' label = 'Convert to Maya 2016' description = 'Converting Scenes to Maya 2016' icon = 'https://cdn.icon-icons.com/icons2/1508/PNG/512/maya_103816.png' output_folder = '' def discover(self, session, entities, event): """Return true if the action is discoverable. Action is discoverable if all entities are Tasks or AssetVersions.""" if not entities: self.logger.info('Selection is not valid for entities: {}'.format(entities)) return False for entity_type, entity_id in entities: if entity_type in ('AssetVersion', 'Component'): continue elif entity_type == 'TypedContext' and session.get(entity_type, entity_id).entity_type == 'Task': continue else: self.logger.info('Selection is not valid. Entity type is {}'.format(entity_type)) return False self.logger.info('Selection is valid') return True def launch(self, session, entities, event): values = event['data']['values'] self.output_folder = values.pop('output_folder', '') components = {comp_id for k, comp_id in values.items() # Get only scene keys and check their boolean state if k.startswith('scene') and values.get('do|{}'.format(k.split('|', 1)[-1]))} user_id = event['source']['user']['id'] self._async_submit(components, user_id) return { 'success': True, 'message': 'Started submitting scenes' } @asynchronous def _async_submit(self, components, user_id): # Create new session as sessions are not guaranteed to be thread-safe. session = ftrack_api.Session(auto_connect_event_hub=False, plugin_paths=[]) # Creating ftrack job job = session.create('Job', { 'user_id': user_id, 'status': 'running', }) try: location = session.query('Location where name is "ftrack.unmanaged"').first() i = 0 for component_id in components: component = session.get('Component', component_id) input_filepath = location.get_filesystem_path(component).replace('\\', '/') # TODO: Add name from ftrack hierarchy not the input_filepath _update_job(job, 'Uploading {}/{} - {}'.format(i + 1, len(components), os.path.basename(input_filepath)), session) try: self._submit_scene(input_filepath) except Exception as err: self.logger.exception('Uploading scene {} failed\n{}'.format(input_filepath, err)) else: i += 1 if i > 1: _update_job(job, '{}/{} scenes submitted to Deadline'.format(i, len(components)), session, status='done') else: _update_job(job, 'Submission of all {} scenes failed', session, status='failed') except BaseException as err: self.logger.exception('Action failed\n{}'.format(err)) session.rollback() _update_job(job, 'Action failed. Check logs for further information', session, status='failed') def _submit_scene(self, input_filepath): output_filepath = os.path.join(self.output_folder, os.path.basename(input_filepath)).replace('\\', '/') copier = FtrackSendMaya2016Constructor(input_filepath, output_filepath) return copier.normal_submit(job_data=None) def interface(self, session, entities, event): """Return interface.""" values = event['data'].get('values', {}) if values: return None items = [] task = None for entity_type, entity_id in entities: task, components = _get_components(session, entity_type, entity_id) if not components: continue components.sort(key=lambda x: -x['version']['version']) components_options = [ {'label': 'v{:03d}'.format(component['version']['version']), 'value': component['id']} for component in components ] items += [{ 'label': ' ' * 40 + '{} / {} / {}'.format( task['parent']['parent']['name'], task['parent']['name'], task['name']), 'name': 'do|{}'.format(task['id']), 'type': 'boolean', 'value': True }, { 'label': 'Scene', 'name': 'scene|{}'.format(task['id']), 'type': 'enumerator', 'value': components_options[0]['value'], 'data': components_options }, { 'value': '---', 'type': 'label' }] if not items: items.append({ 'value': '- No any **scene** component found!', 'type': 'label' }) else: from datetime import datetime from sc.ftrack_utils import ftrack_paths default_path = ftrack_paths.getPath( task, template=['pfxWorkBase'], return_format='single', session=session) output_folder = os.path.join( default_path, 'Data_Out', '{:%Y-%m-%d}'.format(datetime.now())) if default_path else '' items += [ { 'label': 'Output Folder: ', 'type': 'text', 'value': os.path.normpath(output_folder), 'name': 'output_folder' }, { 'type': 'form', 'title': 'Select Scenes for Convert', 'submit_button_label': 'Start' } ] return items # noinspection PyUnusedLocal def register(session, **kw): """Register plugin. Called when used as an plugin.""" # Validate that session is an instance of ftrack_api.Session. If not, # assume that register is being called from an old or incompatible API and # return without doing anything. if not isinstance(session, ftrack_api.session.Session): return action_handler = ConvertToMaya2016Action(session) action_handler.register() if __name__ == '__main__': logging.basicConfig(level=logging.INFO) s = ftrack_api.Session() register(s) # Wait for events logging.info('Registered actions and listening for events. Use Ctrl-C to abort.') s.event_hub.wait()
Editor is loading...