Merge branch 'develop' into feature/OP-3445_tray-publisher-editorial

This commit is contained in:
Jakub Jezek 2022-07-12 17:12:08 +02:00
commit cd95198026
No known key found for this signature in database
GPG key ID: 730D7C02726179A7
5 changed files with 102 additions and 15 deletions

View file

@ -503,6 +503,13 @@ class CreatedInstance:
label = self.subset_name
return label
@property
def group_label(self):
label = self._data.get("group")
if label:
return label
return self.creator.get_group_label()
@property
def creator_identifier(self):
return self.creator.identifier

View file

@ -1,5 +1,4 @@
import copy
import logging
from abc import (
ABCMeta,
@ -47,6 +46,9 @@ class BaseCreator:
# Label shown in UI
label = None
group_label = None
# Cached group label after first call 'get_group_label'
_cached_group_label = None
# Variable to store logger
_log = None
@ -85,11 +87,13 @@ class BaseCreator:
Default implementation returns plugin's family.
"""
return self.family
@abstractproperty
def family(self):
"""Family that plugin represents."""
pass
@property
@ -98,8 +102,35 @@ class BaseCreator:
return self.create_context.project_name
def get_group_label(self):
"""Group label under which are instances grouped in UI.
Default implementation use attributes in this order:
- 'group_label' -> 'label' -> 'identifier'
Keep in mind that 'identifier' use 'family' by default.
Returns:
str: Group label that can be used for grouping of instances in UI.
Group label can be overriden by instance itself.
"""
if self._cached_group_label is None:
label = self.identifier
if self.group_label:
label = self.group_label
elif self.label:
label = self.label
self._cached_group_label = label
return self._cached_group_label
@property
def log(self):
"""Logger of the plugin.
Returns:
logging.Logger: Logger with name of the plugin.
"""
if self._log is None:
from openpype.api import Logger
@ -107,10 +138,30 @@ class BaseCreator:
return self._log
def _add_instance_to_context(self, instance):
"""Helper method to ad d"""
"""Helper method to add instance to create context.
Instances should be stored to DCC workfile metadata to be able reload
them and also stored to CreateContext in which is creator plugin
existing at the moment to be able use it without refresh of
CreateContext.
Args:
instance (CreatedInstance): New created instance.
"""
self.create_context.creator_adds_instance(instance)
def _remove_instance_from_context(self, instance):
"""Helper method to remove instance from create context.
Instances must be removed from DCC workfile metadat aand from create
context in which plugin is existing at the moment of removement to
propagate the change without restarting create context.
Args:
instance (CreatedInstance): Instance which should be removed.
"""
self.create_context.creator_removed_instance(instance)
@abstractmethod
@ -121,6 +172,7 @@ class BaseCreator:
- must expect all data that were passed to init in previous
implementation
"""
pass
@abstractmethod
@ -147,6 +199,7 @@ class BaseCreator:
self._add_instance_to_context(instance)
```
"""
pass
@abstractmethod
@ -154,9 +207,10 @@ class BaseCreator:
"""Store changes of existing instances so they can be recollected.
Args:
update_list(list<UpdateData>): Gets list of tuples. Each item
update_list(List[UpdateData]): Gets list of tuples. Each item
contain changed instance and it's changes.
"""
pass
@abstractmethod
@ -167,9 +221,10 @@ class BaseCreator:
'True' if did so.
Args:
instance(list<CreatedInstance>): Instance objects which should be
instance(List[CreatedInstance]): Instance objects which should be
removed.
"""
pass
def get_icon(self):
@ -177,6 +232,7 @@ class BaseCreator:
Can return path to image file or awesome icon name.
"""
return self.icon
def get_dynamic_data(
@ -187,6 +243,7 @@ class BaseCreator:
These may be get dynamically created based on current context of
workfile.
"""
return {}
def get_subset_name(
@ -211,6 +268,7 @@ class BaseCreator:
project_name(str): Project name.
host_name(str): Which host creates subset.
"""
dynamic_data = self.get_dynamic_data(
variant, task_name, asset_doc, project_name, host_name
)
@ -237,9 +295,10 @@ class BaseCreator:
keys/values when plugin attributes change.
Returns:
list<AbtractAttrDef>: Attribute definitions that can be tweaked for
List[AbtractAttrDef]: Attribute definitions that can be tweaked for
created instance.
"""
return self.instance_attr_defs
@ -297,6 +356,7 @@ class Creator(BaseCreator):
Returns:
str: Short description of family.
"""
return self.description
def get_detail_description(self):
@ -307,6 +367,7 @@ class Creator(BaseCreator):
Returns:
str: Detailed description of family for artist.
"""
return self.detailed_description
def get_default_variants(self):
@ -318,8 +379,9 @@ class Creator(BaseCreator):
By default returns `default_variants` value.
Returns:
list<str>: Whisper variants for user input.
List[str]: Whisper variants for user input.
"""
return copy.deepcopy(self.default_variants)
def get_default_variant(self):
@ -338,11 +400,13 @@ class Creator(BaseCreator):
"""Plugin attribute definitions needed for creation.
Attribute definitions of plugin that define how creation will work.
Values of these definitions are passed to `create` method.
NOTE:
Convert method should be implemented which should care about updating
keys/values when plugin attributes change.
Note:
Convert method should be implemented which should care about
updating keys/values when plugin attributes change.
Returns:
list<AbtractAttrDef>: Attribute definitions that can be tweaked for
List[AbtractAttrDef]: Attribute definitions that can be tweaked for
created instance.
"""
return self.pre_create_attr_defs

View file

@ -447,7 +447,22 @@ class ExtractReview(pyblish.api.InstancePlugin):
input_is_sequence = self.input_is_sequence(repre)
input_allow_bg = False
first_sequence_frame = None
if input_is_sequence and repre["files"]:
# Calculate first frame that should be used
cols, _ = clique.assemble(repre["files"])
input_frames = list(sorted(cols[0].indexes))
first_sequence_frame = input_frames[0]
# WARNING: This is an issue as we don't know if first frame
# is with or without handles!
# - handle start is added but how do not know if we should
output_duration = (output_frame_end - output_frame_start) + 1
if (
without_handles
and len(input_frames) - handle_start >= output_duration
):
first_sequence_frame += handle_start
ext = os.path.splitext(repre["files"][0])[1].replace(".", "")
if ext in self.alpha_exts:
input_allow_bg = True
@ -467,6 +482,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
"resolution_height": instance.data.get("resolutionHeight"),
"origin_repre": repre,
"input_is_sequence": input_is_sequence,
"first_sequence_frame": first_sequence_frame,
"input_allow_bg": input_allow_bg,
"with_audio": with_audio,
"without_handles": without_handles,
@ -545,9 +561,9 @@ class ExtractReview(pyblish.api.InstancePlugin):
if temp_data["input_is_sequence"]:
# Set start frame of input sequence (just frame in filename)
# - definition of input filepath
ffmpeg_input_args.append(
"-start_number {}".format(temp_data["output_frame_start"])
)
ffmpeg_input_args.extend([
"-start_number", str(temp_data["first_sequence_frame"])
])
# TODO add fps mapping `{fps: fraction}` ?
# - e.g.: {

View file

@ -436,7 +436,7 @@ class InstanceCardView(AbstractInstanceView):
instances_by_group = collections.defaultdict(list)
identifiers_by_group = collections.defaultdict(set)
for instance in self.controller.instances:
group_name = instance.creator_label
group_name = instance.group_label
instances_by_group[group_name].append(instance)
identifiers_by_group[group_name].add(
instance.creator_identifier

View file

@ -519,7 +519,7 @@ class InstanceListView(AbstractInstanceView):
instances_by_group_name = collections.defaultdict(list)
group_names = set()
for instance in self.controller.instances:
group_label = instance.creator_label
group_label = instance.group_label
group_names.add(group_label)
instances_by_group_name[group_label].append(instance)