Action Maya Convert 2016
unknown
python
4 years ago
9.4 kB
7
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...