From 785925f1cc2deae1387ea91b903779a832df08f0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 16:59:38 +0100 Subject: [PATCH] Vertical alignment distribution of data fix - Adjusted vertical alignment and distribution of data in the code to ensure proper handling and organization of clip metadata. --- client/ayon_hiero/api/plugin.py | 134 ++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 49 deletions(-) diff --git a/client/ayon_hiero/api/plugin.py b/client/ayon_hiero/api/plugin.py index 6ecef54..96d390a 100644 --- a/client/ayon_hiero/api/plugin.py +++ b/client/ayon_hiero/api/plugin.py @@ -1,7 +1,7 @@ import os -from pprint import pformat import re import uuid +from copy import deepcopy import hiero @@ -418,8 +418,6 @@ def __init__(self, cls, context, path, **options): # inject folder data to representation dict folder_entity = self.context["folder"] self.data["folderAttributes"] = folder_entity["attrib"] - log.info("__init__ self.data: `{}`".format(pformat(self.data))) - log.info("__init__ options: `{}`".format(pformat(options))) # add active components to class if self.new_sequence: @@ -657,6 +655,10 @@ class PublishClip: Returns: hiero.core.TrackItem: hiero track item object with AYON tag """ + vertical_clip_match = {} + vertical_clip_used = {} + tag_data = {} + types = { "shot": "shot", "folder": "folder", @@ -672,7 +674,7 @@ class PublishClip: rename_default = False hierarchy_default = "{_folder_}/{_sequence_}/{_track_}" clip_name_default = "shot_{_trackIndex_:0>3}_{_clipIndex_:0>4}" - product_name_default = "" + base_product_name_default = "" review_track_default = "< none >" product_type_default = "plate" count_from_default = 10 @@ -700,8 +702,6 @@ def __init__( rename_index=0): self.rename_index = rename_index - self.vertical_clip_match = dict() - self.tag_data = dict() # adding ui inputs if any self.pre_create_data = pre_create_data or {} @@ -724,9 +724,6 @@ def __init__( if data: self.tag_data.update(data) - # add publish attribute to tag data - self.tag_data.update({"publish": True}) - # populate default data before we get other attributes self._populate_track_item_default_data() @@ -795,22 +792,24 @@ def _populate_attributes(self): log.debug( "____ self.shot_num: {}".format(self.shot_num)) - # publisher ui attribute inputs or default values if gui was not used + # publisher ui attribute inputs or default values if gui was not used def get(key): """Shorthand access for code readability""" return self.pre_create_data.get(key) # ui_inputs data or default values if gui was not used - self.rename = self.pre_create_data.get("clipRename", self.rename_default) + self.rename = self.pre_create_data.get( + "clipRename", self.rename_default) self.clip_name = get("clipName") or self.clip_name_default self.hierarchy = get("hierarchy") or self.hierarchy_default self.count_from = get("countFrom") or self.count_from_default self.count_steps = get("countSteps") or self.count_steps_default - self.product_name = get("productName") or self.product_name_default + self.base_product_name = ( + get("productName") or self.base_product_name_default) self.product_type = get("productType") or self.product_type_default self.vertical_sync = get("vSyncOn") or self.vertical_sync_default self.driving_layer = get("vSyncTrack") or self.driving_layer_default - self.review_track = get("reviewTrack") or self.review_track_default + self.review_track = get("reviewableTrack") or self.review_track_default self.audio = get("audio") or False self.hierarchy_data = { @@ -819,13 +818,12 @@ def get(key): } # build product name from layer name - if self.product_name == "": - self.product_name = self.track_name + if self.base_product_name == "": + self.base_product_name = self.track_name # create product for publishing self.product_name = ( - self.product_type + self.product_name.capitalize() - ) + f"{self.product_type}{self.base_product_name.capitalize()}") def _replace_hash_to_expression(self, name, text): """ Replace hash with number in correct padding. """ @@ -842,17 +840,22 @@ def _convert_to_tag_data(self): # define vertical sync attributes hero_track = True self.review_layer = "" - if self.vertical_sync: + if ( + self.vertical_sync + and self.track_name != self.driving_layer + ): # check if track name is not in driving layer - if self.track_name not in self.driving_layer: - # if it is not then define vertical sync as None - hero_track = False + # if it is not then define vertical sync as None + hero_track = False # increasing steps by index of rename iteration self.count_steps *= self.rename_index - hierarchy_formatting_data = dict() + hierarchy_formatting_data = {} + hierarchy_data = deepcopy(self.hierarchy_data) _data = self.track_item_default_data.copy() + + # QUESTION: what is this for? it seems we always have pre_create_data if self.pre_create_data: # adding tag metadata from ui @@ -877,48 +880,81 @@ def _convert_to_tag_data(self): _data.update({"shot": self.shot_num}) # solve # in test to pythonic expression - for _key, _value in self.hierarchy_data.items(): + for _key, _value in hierarchy_data.items(): if "#" not in _value: continue - self.hierarchy_data[_key] = self._replace_hash_to_expression( - _key, _value - ) + hierarchy_data[_key] = self._replace_hash_to_expression( + _key, _value) # fill up pythonic expresisons in hierarchy data - for _key, _value in self.hierarchy_data.items(): - hierarchy_formatting_data[_key] = _value.format(**_data) + for _key, _value in hierarchy_data.items(): + formatted_value = _value.format(**_data) + hierarchy_formatting_data[_key] = formatted_value + self.tag_data[_key] = formatted_value else: # if no gui mode then just pass default data - hierarchy_formatting_data = self.hierarchy_data + hierarchy_formatting_data = hierarchy_data - tag_hierarchy_data = self._solve_tag_hierarchy_data( + tag_instance_data = self._solve_tag_instance_data( hierarchy_formatting_data ) - tag_hierarchy_data.update({"heroTrack": True}) + tag_instance_data.update({"heroTrack": True}) if hero_track and self.vertical_sync: - self.vertical_clip_match.update({ - (self.clip_in, self.clip_out): tag_hierarchy_data - }) + self.vertical_clip_match.update( + {(self.clip_in, self.clip_out): tag_instance_data} + ) if not hero_track and self.vertical_sync: # driving layer is set as negative match - for (_in, _out), hero_data in self.vertical_clip_match.items(): - hero_data.update({"heroTrack": False}) - if _in == self.clip_in and _out == self.clip_out: - data_product_name = hero_data["productName"] - # add track index in case duplicity of names in hero data - if self.product_name in data_product_name: - hero_data["productName"] = self.product_name + str( - self.track_index) - # in case track name and product name is the same then add - if self.product_name == self.track_name: - hero_data["productName"] = self.product_name - # assign data to return hierarchy data to tag - tag_hierarchy_data = hero_data + for (hero_in, hero_out), hero_data in self.vertical_clip_match.items(): # noqa + """Iterate over all clips in vertical sync match + + If clip frame range is outside of hero clip frame range + then skip this clip and do not add to hierarchical shared + metadata to them. + """ + if self.clip_in < hero_in and self.clip_out > hero_out: + continue + + _distrib_data = deepcopy(hero_data) + _distrib_data["heroTrack"] = False + data_product_name = hero_data["productName"] + + # get used names list for duplicity check + used_names_list = self.vertical_clip_used.setdefault( + data_product_name, [] + ) + + clip_product_name = self.product_name + + # in case track name and product name is the same then add + if self.base_product_name == self.track_name: + clip_product_name = self.product_name + + # add track index in case duplicity of names in hero data + # INFO: this is for case where hero clip product name + # is the same as current clip product name + if clip_product_name in data_product_name: + clip_product_name = ( + f"{clip_product_name}{self.track_index}") + + # in case track clip product name had been already used + # then add product name with clip index + if clip_product_name in used_names_list: + clip_product_name = ( + f"{clip_product_name}{self.rename_index}") + + _distrib_data["productName"] = clip_product_name + # assign data to return hierarchy data to tag + tag_instance_data = _distrib_data + + # add used product name to used list to avoid duplicity + used_names_list.append(clip_product_name) + break # add data to return data dict - self.tag_data.update(tag_hierarchy_data) + self.tag_data.update(tag_instance_data) # add uuid to tag data self.tag_data["uuid"] = str(uuid.uuid4()) @@ -929,7 +965,7 @@ def _convert_to_tag_data(self): else: self.tag_data.update({"reviewTrack": None}) - def _solve_tag_hierarchy_data(self, hierarchy_formatting_data): + def _solve_tag_instance_data(self, hierarchy_formatting_data): """ Solve tag data from hierarchy data and templates. """ # fill up clip name and hierarchy keys hierarchy_filled = self.hierarchy.format(**hierarchy_formatting_data)