From a88b1f1a33c1dada33a67cbe488776ce0c5f0b22 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 7 Jul 2022 22:02:15 +0200 Subject: [PATCH] trayp: editorial family wip --- openpype/hosts/traypublisher/api/editorial.py | 41 ------- openpype/hosts/traypublisher/api/plugin.py | 86 +------------ .../plugins/create/create_editorial.py | 116 ++++++++++++++++-- openpype/pipeline/create/creator_plugins.py | 6 + 4 files changed, 112 insertions(+), 137 deletions(-) delete mode 100644 openpype/hosts/traypublisher/api/editorial.py diff --git a/openpype/hosts/traypublisher/api/editorial.py b/openpype/hosts/traypublisher/api/editorial.py deleted file mode 100644 index 316163b2fa..0000000000 --- a/openpype/hosts/traypublisher/api/editorial.py +++ /dev/null @@ -1,41 +0,0 @@ - -import os -import opentimelineio as otio -from openpype import lib as plib - -from openpype.pipeline import ( - Creator, - CreatedInstance -) - -from .pipeline import ( - list_instances, - update_instances, - remove_instances, - HostContext, -) - - - -class CreateEditorialInstance: - """Create Editorial OTIO timeline""" - - def __init__(self, file_path, extension=None, resources_dir=None): - self.file_path = file_path - self.video_extension = extension or ".mov" - self.resources_dir = resources_dir - - def create(self): - - # get editorial sequence file into otio timeline object - extension = os.path.splitext(self.file_path)[1] - kwargs = {} - if extension == ".edl": - # EDL has no frame rate embedded so needs explicit - # frame rate else 24 is asssumed. - kwargs["rate"] = plib.get_asset()["data"]["fps"] - - instance.data["otio_timeline"] = otio.adapters.read_from_file( - file_path, **kwargs) - - self.log.info(f"Added OTIO timeline from: `{file_path}`") diff --git a/openpype/hosts/traypublisher/api/plugin.py b/openpype/hosts/traypublisher/api/plugin.py index ae9e93fd60..94f6e7487f 100644 --- a/openpype/hosts/traypublisher/api/plugin.py +++ b/openpype/hosts/traypublisher/api/plugin.py @@ -3,12 +3,7 @@ from openpype.pipeline import ( CreatedInstance ) from openpype.lib import ( - FileDef, - TextDef, - NumberDef, - EnumDef, - BoolDef, - FileDefItem + FileDef ) from .pipeline import ( @@ -93,82 +88,3 @@ class SettingsCreator(TrayPublishCreator): "default_variants": item_data["default_variants"] } ) - - -class EditorialCreator(TrayPublishCreator): - create_allow_context_change = True - - extensions = [] - - def create(self, subset_name, data, pre_create_data): - # TODO: create otio instance - # TODO: create clip instances - - # Pass precreate data to creator attributes - data["creator_attributes"] = pre_create_data - data["editorial_creator"] = True - # Create new instance - new_instance = CreatedInstance(self.family, subset_name, data, self) - # Host implementation of storing metadata about instance - HostContext.add_instance(new_instance.data_to_store()) - # Add instance to current context - self._add_instance_to_context(new_instance) - - def get_instance_attr_defs(self): - if self.identifier == "editorial.simple": - return [ - FileDef( - "sequence_filepath", - folders=False, - extensions=self.sequence_extensions, - allow_sequences=self.allow_sequences, - label="Filepath", - ) - ] - else: - return [ - FileDef( - "sequence_filepath", - folders=False, - extensions=self.sequence_extensions, - allow_sequences=self.allow_sequences, - label="Sequence filepath", - ), - FileDef( - "clip_source_folder", - folders=True, - extensions=self.clip_extensions, - allow_sequences=False, - label="Clips' Source folder", - ), - TextDef("text input"), - NumberDef("number input"), - EnumDef("enum input", { - "value1": "label1", - "value2": "label2" - }), - BoolDef("bool input") - ] - - @classmethod - def from_settings(cls, item_data): - identifier = item_data["identifier"] - family = item_data["family"] - if not identifier: - identifier = "settings_{}".format(family) - return type( - "{}{}".format(cls.__name__, identifier), - (cls, ), - { - "family": family, - "identifier": identifier, - "label": item_data["label"].strip(), - "icon": item_data["icon"], - "description": item_data["description"], - "detailed_description": item_data["detailed_description"], - "sequence_extensions": item_data["sequence_extensions"], - "clip_extensions": item_data["clip_extensions"], - "allow_sequences": item_data["allow_sequences"], - "default_variants": item_data["default_variants"] - } - ) diff --git a/openpype/hosts/traypublisher/plugins/create/create_editorial.py b/openpype/hosts/traypublisher/plugins/create/create_editorial.py index 8b2af8973b..49fba65711 100644 --- a/openpype/hosts/traypublisher/plugins/create/create_editorial.py +++ b/openpype/hosts/traypublisher/plugins/create/create_editorial.py @@ -1,25 +1,119 @@ import os -from pprint import pformat -from openpype.api import get_project_settings, Logger +import opentimelineio as otio +from openpype.api import get_project_settings +from openpype.hosts.traypublisher.api.plugin import TrayPublishCreator +from openpype.pipeline.create.creator_plugins import InvisibleCreator -log = Logger.get_logger(__name__) +from openpype.pipeline import CreatedInstance + +from openpype.lib import ( + FileDef, + TextDef, + NumberDef, + EnumDef, + BoolDef +) + +from openpype.hosts.traypublisher.api.pipeline import HostContext def CreateEditorial(): - from openpype.hosts.traypublisher.api.plugin import EditorialCreator - project_name = os.environ["AVALON_PROJECT"] project_settings = get_project_settings(project_name) editorial_creators = project_settings["traypublisher"]["editorial_creators"] - global_variables = globals() - for item in editorial_creators: - log.debug(pformat(item)) +class EditorialClipInstanceCreator(InvisibleCreator): + identifier = "editorial.clip" + family = "clip" - dynamic_plugin = EditorialCreator.from_settings(item) - global_variables[dynamic_plugin.__name__] = dynamic_plugin + def create(self, instance_data, source_data): + # instance_data > asset, task_name, variant, family + # source_data > additional data + self.log.info(f"instance_data: {instance_data}") + self.log.info(f"source_data: {source_data}") -CreateEditorial() +class EditorialSimpleCreator(TrayPublishCreator): + + label = "Editorial Simple" + family = "editorial" + identifier = "editorial.simple" + default_variants = [ + "main", + "review" + ] + description = "Editorial files to generate shots." + detailed_description = """ +Supporting publishing new shots to project +or updating already created. Publishing will create OTIO file. +""" + icon = "fa.file" + + def create(self, subset_name, data, pre_create_data): + # TODO: create otio instance + otio_timeline = self._create_otio_instance( + subset_name, data, pre_create_data) + + # TODO: create clip instances + editorial_clip_creator = self.create_context.creators["editorial.clip"] + editorial_clip_creator.create({}, {}) + + def _create_otio_instance(self, subset_name, data, pre_create_data): + # from openpype import lib as plib + + # get path of sequence + file_path_data = pre_create_data["sequence_filepath_data"] + file_path = os.path.join( + file_path_data["directory"], file_path_data["filenames"][0]) + + self.log.info(f"file_path: {file_path}") + + # get editorial sequence file into otio timeline object + extension = os.path.splitext(file_path)[1] + kwargs = {} + if extension == ".edl": + # EDL has no frame rate embedded so needs explicit + # frame rate else 24 is asssumed. + kwargs["rate"] = float(25) + # plib.get_asset()["data"]["fps"] + + self.log.info(f"kwargs: {kwargs}") + otio_timeline = otio.adapters.read_from_file( + file_path, **kwargs) + + # Pass precreate data to creator attributes + data.update({ + "creator_attributes": pre_create_data, + "editorial_creator": True + + }) + + self._create_instance(self.family, subset_name, data) + + return otio_timeline + + def _create_instance(self, family, subset_name, data): + # Create new instance + new_instance = CreatedInstance(family, subset_name, data, self) + # Host implementation of storing metadata about instance + HostContext.add_instance(new_instance.data_to_store()) + # Add instance to current context + self._add_instance_to_context(new_instance) + + def get_instance_attr_defs(self): + return [ + FileDef( + "sequence_filepath_data", + folders=False, + extensions=[ + ".edl", + ".xml", + ".aaf", + ".fcpxml" + ], + allow_sequences=False, + label="Filepath", + ) + ] diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index 8006d4f4f8..778d6846b2 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -342,6 +342,12 @@ class Creator(BaseCreator): return self.pre_create_attr_defs +class InvisibleCreator(BaseCreator): + @abstractmethod + def create(self, instance_data, source_data): + pass + + class AutoCreator(BaseCreator): """Creator which is automatically triggered without user interaction.