Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Flame creators to new publisher #33

Open
wants to merge 34 commits into
base: develop
Choose a base branch
from

Conversation

robin-ynput
Copy link
Contributor

@robin-ynput robin-ynput commented Nov 5, 2024

Changelog Description

resolve #10
Make flame creators use the Creator API and new widget. Publishable products are now listed as individual instances following a similar logic than Hiero and Resolve.

flame_ayon

Done:

Testing notes:

In Flame:

  • Create a timeline with clips associated to movie and img-sequence media
  • From AYON Menu (right click)
  • Create and publish product(s) of type shot, audio, plate and review from there

Tested locally on Flame 2024.2

@robin-ynput robin-ynput added type: enhancement Improvement of existing functionality or minor addition sponsored This is directly sponsored by a client or community member bump minor labels Nov 5, 2024
@robin-ynput robin-ynput self-assigned this Nov 5, 2024
@robin-ynput robin-ynput marked this pull request as ready for review November 11, 2024 23:57
Comment on lines +214 to +223

attr_defs = instance.creator_attributes.attr_defs

if "review" not in changes:
continue

review_value = changes["review"]
reviewable_source = next(
attr_def
for attr_def in attr_defs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
attr_defs = instance.creator_attributes.attr_defs
if "review" not in changes:
continue
review_value = changes["review"]
reviewable_source = next(
attr_def
for attr_def in attr_defs
if "review" not in changes:
continue
attr_defs = instance.creator_attributes.attr_defs
review_value = changes["review"]
reviewable_source = next(
attr_def
for attr_def in attr_defs

label="Review Track",
tooltip=("Selecting source from review tracks."),
items=gui_tracks,
disabled=not current_review,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
disabled=not current_review,
enabled=current_review,

for attr_def in attr_defs
if attr_def.key == "reviewTrack"
)
reviewable_source.disabled = not review_value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
reviewable_source.disabled = not review_value
reviewable_source.enabled = review_value

Comment on lines +533 to +536
def create(self, subset_name, instance_data, pre_create_data):
super(CreateShotClip, self).create(subset_name,
instance_data,
pre_create_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def create(self, subset_name, instance_data, pre_create_data):
super(CreateShotClip, self).create(subset_name,
instance_data,
pre_create_data)
def create(self, product_name, instance_data, pre_create_data):
super().create(
product_name,
instance_data,
pre_create_data)

Comment on lines +544 to +546
audio_clips = []
for audio_track in self.sequence.audio_tracks:
audio_clips.append(audio_track.segments)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
audio_clips = []
for audio_track in self.sequence.audio_tracks:
audio_clips.append(audio_track.segments)
audio_clips = [
audio_track.segments
for audio_track in self.sequence.audio_tracks
]

Comment on lines +558 to +559
sorted_selected_segments = list()
unsorted_selected_segments = list()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already defined below

Suggested change
sorted_selected_segments = list()
unsorted_selected_segments = list()

for idx, segment in enumerate(sorted_selected_segments):

clip_index = str(uuid.uuid4())
segment_instance_data = instance_data.copy()
Copy link
Member

@iLLiCiTiT iLLiCiTiT Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.copy() on dictionary is the same as dict(instance_data) which does not create copy of value objects (e.g. lists or nested dictionaries)

Suggested change
segment_instance_data = instance_data.copy()
segment_instance_data = copy.deepcopy(instance_data)

Comment on lines +615 to +620
prev_instances = [
inst for inst_id, inst
in self.create_context.instances_by_id.items()
if inst_id == inst_data["instance_id"]
]
creator.remove_instances(prev_instances)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
prev_instances = [
inst for inst_id, inst
in self.create_context.instances_by_id.items()
if inst_id == inst_data["instance_id"]
]
creator.remove_instances(prev_instances)
prev_instance = self.create_context.instances_by_id.get(
inst_data["instance_id"]
)
if prev_instance is not None:
creator.remove_instances([prev_instance])

Comment on lines +654 to +656
"label": (
f"{shot_folder_path} shot"
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"label": (
f"{shot_folder_path} shot"
),
"label": f"{shot_folder_path} shot",

Comment on lines +772 to +778
if instance_data["audio"]:
sub_creators = (
"io.ayon.creators.flame.plate",
"io.ayon.creators.flame.audio"
)
else:
sub_creators = ("io.ayon.creators.flame.plate",)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if instance_data["audio"]:
sub_creators = (
"io.ayon.creators.flame.plate",
"io.ayon.creators.flame.audio"
)
else:
sub_creators = ("io.ayon.creators.flame.plate",)
sub_creators = ["io.ayon.creators.flame.plate"]
if instance_data["audio"]:
sub_creators.append(
"io.ayon.creators.flame.audio"
)

sub_creators = ("io.ayon.creators.flame.plate",)

for sub_creator_id in sub_creators:
sub_instance_data = instance_data.copy()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sub_instance_data = instance_data.copy()
sub_instance_data = copy.deepcopy(instance_data)

Comment on lines +830 to +836
if _CONTENT_ID in marker_data:
for creator_id, data in marker_data[_CONTENT_ID].items():
self._create_and_add_instance(
data, creator_id, segment, instances)

else:
instances.extend(self._collect_legacy_instance(segment, marker_data))
Copy link
Member

@iLLiCiTiT iLLiCiTiT Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if _CONTENT_ID in marker_data:
for creator_id, data in marker_data[_CONTENT_ID].items():
self._create_and_add_instance(
data, creator_id, segment, instances)
else:
instances.extend(self._collect_legacy_instance(segment, marker_data))
# Legacy instances handling
if _CONTENT_ID not in marker_data:
instances.extend(
self._collect_legacy_instance(segment, marker_data)
)
continue
for creator_id, data in marker_data[_CONTENT_ID].items():
self._create_and_add_instance(
data, creator_id, segment, instances)

default_variant = "Main"

def collect_instances(self):
@staticmethod
def _get_project_workfile_filepath():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be function somehwere in ayon_flame.api? (I have no context so maybe not)


if instance.data.get("reviewTrack") is not None:
instance.data["reviewAudio"] = True
instance.data.pop("reviewTrack")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
instance.data.pop("reviewTrack")
# Remove review track to avoid creation of reviewable
# for the instance
instance.data.pop("reviewTrack")

break

else:
raise ValueError("Could not retrieve source from selected segments.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something that is "artist" error or "code" error? If it is something that artist should know about then use PublishError (from ayon_core.pipeline import PublishError). It will show the error message to user, otherwise he'll see "This is not your fault".

Copy link
Member

@iLLiCiTiT iLLiCiTiT Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW for code readability I would use this, technically the same, but easier to read intention (not pushing tho).

    segment_item = None
    for item in instance.context.data["flameSelectedSegments"]:
        item_data = ayfapi.get_segment_data_marker(item) or {}
        if item_data.get("clip_index") == instance.data["clip_index"]:
             segment_item = item
             break

    if segment_item is None:
        raise PublishError("Could not retrieve source from selected segments.")

Comment on lines +125 to +135
# make sure there is not NoneType rather 0
if head is None:
head = 0
if tail is None:
tail = 0

# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# make sure there is not NoneType rather 0
if head is None:
head = 0
if tail is None:
tail = 0
# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)
# Make sure there is not None and negative number
head = abs(head or 0)
tail = abs(tail or 0)
# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)

Comment on lines +125 to +135
# make sure there is not NoneType rather 0
if head is None:
head = 0
if tail is None:
tail = 0

# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)
Copy link
Member

@iLLiCiTiT iLLiCiTiT Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# make sure there is not NoneType rather 0
if head is None:
head = 0
if tail is None:
tail = 0
# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)
# Make sure there is not None and negative number
head = abs(head or 0)
tail = abs(tail or 0)

BTW did you really wanted to use abs? Should that be clamped to 0 instead?

Suggested change
# make sure there is not NoneType rather 0
if head is None:
head = 0
if tail is None:
tail = 0
# make sure value is absolute
if head != 0:
head = abs(head)
if tail != 0:
tail = abs(tail)
# Make sure there is not None and clamp to 0
if head is None or head < 0:
head = 0
if tail is None or head < 0:
tail = 0

Comment on lines +256 to +264
split_comments = []
if "," in comment_string:
split_comments.extend(comment_string.split(","))
elif ";" in comment_string:
split_comments.extend(comment_string.split(";"))
else:
split_comments.append(comment_string)

return split_comments
Copy link
Member

@iLLiCiTiT iLLiCiTiT Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires import re.

Suggested change
split_comments = []
if "," in comment_string:
split_comments.extend(comment_string.split(","))
elif ";" in comment_string:
split_comments.extend(comment_string.split(";"))
else:
split_comments.append(comment_string)
return split_comments
return re.split(r",|;", comment_string)

Or to be more obvious

Suggested change
split_comments = []
if "," in comment_string:
split_comments.extend(comment_string.split(","))
elif ";" in comment_string:
split_comments.extend(comment_string.split(";"))
else:
split_comments.append(comment_string)
return split_comments
pattern = "|".join([",", ";"])
return re.split(pattern, comment_string)

class CollectShot(pyblish.api.InstancePlugin):
"""Collect new shots."""

order = order = pyblish.api.CollectorOrder - 0.095
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
order = order = pyblish.api.CollectorOrder - 0.095
order = pyblish.api.CollectorOrder - 0.095

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to run this plugin much earlier? e.g. pyblish.api.CollectorOrder - 0.49? If not please describe why not. Does not happen in this PR, but let me know I'll create issue for it if we can't do it now, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bump minor type: enhancement Improvement of existing functionality or minor addition
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AY-6253_Conversion creators in new publisher
3 participants