Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Flame: debugging #3224

Merged
merged 56 commits into from
May 30, 2022
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f7fc6a3
flame: fixing attr_name issue
jakubjezek001 May 10, 2022
21b83e3
flame" adding empty families to workfile instance
jakubjezek001 May 10, 2022
9483adc
Flame: commenting out effects - not yet implemented
jakubjezek001 May 10, 2022
ff37e61
global: removing `clip` family from excluded - obsolete
jakubjezek001 May 10, 2022
43baf02
flame: refactory MediaInfo class
jakubjezek001 May 11, 2022
c34ecfd
flame: fixing logger
jakubjezek001 May 11, 2022
aac7797
flame: check collection first
jakubjezek001 May 11, 2022
b7f7af4
flame: redundant condition
jakubjezek001 May 11, 2022
7f1b8f7
flame: adding docstrings
jakubjezek001 May 11, 2022
ac16e1f
flame: adding more docstring
jakubjezek001 May 11, 2022
8a1f7c1
flame: fix for single file use
jakubjezek001 May 11, 2022
d5fa437
flame: thumbnail frame number if not `Sequence Publish`
jakubjezek001 May 11, 2022
8892422
flame: attempt to solve issue with single frame imported clip
jakubjezek001 May 11, 2022
12abc9e
flame: thumbnails and mov presets are created correctly now
jakubjezek001 May 11, 2022
df1b5c6
flame: reducing code redundancy
jakubjezek001 May 12, 2022
05faaaa
Merge branch 'bugfix/framerange_op_wrong_duration' into bugfix/OP-319…
jakubjezek001 May 12, 2022
dd77f7c
flame: fixing padding in collection ranges
jakubjezek001 May 12, 2022
aeff57d
flame: expanding retiming features
jakubjezek001 May 12, 2022
ce250a6
flame: debug logging
jakubjezek001 May 12, 2022
ee274f8
flame: solving issue with frame longer renders
jakubjezek001 May 12, 2022
3f91705
flame: improving logging
jakubjezek001 May 12, 2022
71bd7eb
flame: retime is float value
jakubjezek001 May 12, 2022
ababf40
flame: splitting function into smaller parts
jakubjezek001 May 13, 2022
0ae531d
flame: fixing small hickups
jakubjezek001 May 13, 2022
4c06558
Merge branch 'develop' into bugfix/OP-3191_Flame-publishing-bugs
jakubjezek001 May 13, 2022
43aee19
flame: fixing padding if it is higher then needed
jakubjezek001 May 13, 2022
30123ed
flame: adding xml element if it is missing and its path possible
jakubjezek001 May 13, 2022
851df81
flame: treat thumbnail as poster frame
jakubjezek001 May 13, 2022
7d13de9
Flame: add handles including to settings
jakubjezek001 May 16, 2022
3895008
flame: implementing handles include switch
jakubjezek001 May 16, 2022
5c4541c
flame: implementing handles including
jakubjezek001 May 16, 2022
fa1e08f
Merge remote-tracking branch 'pypeclub/bugfix/OP-3191_Flame-publishin…
May 16, 2022
45c445d
removing version change by excident
jakubjezek001 May 16, 2022
c3e5b21
Merge branch 'develop' into bugfix/OP-3191_Flame-publishing-bugs
jakubjezek001 May 16, 2022
3b15167
Flame: adding new attribute to ui
jakubjezek001 May 16, 2022
3ef846b
flame: fixing head and tail calculation
jakubjezek001 May 16, 2022
0699906
Flame: implementing handles inclusion to publishing
jakubjezek001 May 16, 2022
196182f
general: expose lib editorial function to lib init
jakubjezek001 May 16, 2022
6ee42b1
flame: make head and tail with retimed value
jakubjezek001 May 16, 2022
257c589
flame: change editorial function to lib
jakubjezek001 May 16, 2022
056b925
global: fixing false editorial namespace
jakubjezek001 May 16, 2022
9fc70ad
flame: abs number only if not 0
jakubjezek001 May 18, 2022
5e7e6e3
Merge branch 'bugfix/OP-3139_Hiero-published-mp4s-are-one-frame-longe…
jakubjezek001 May 20, 2022
c0ee519
Hound
jakubjezek001 May 24, 2022
e4878ea
Flame: make sure repre name is first segment from tokenizable str
jakubjezek001 May 26, 2022
f96318c
Update openpype/hosts/flame/otio/flame_export.py
jakubjezek001 May 26, 2022
95f836f
Update openpype/hosts/flame/api/render_utils.py
jakubjezek001 May 26, 2022
2d1f7b9
Update openpype/hosts/flame/otio/flame_export.py
jakubjezek001 May 26, 2022
db5d850
Update openpype/hosts/flame/plugins/publish/extract_subset_resources.py
jakubjezek001 May 26, 2022
024874b
Update openpype/hosts/flame/plugins/publish/extract_subset_resources.py
jakubjezek001 May 26, 2022
ab80688
flame: removing unneeded code
jakubjezek001 May 26, 2022
c5787b8
Flame: small bugs
jakubjezek001 May 26, 2022
ae233ce
hiero: PR suggestion
jakubjezek001 May 26, 2022
4cd4124
flame: fixing frame range from editorial
jakubjezek001 May 26, 2022
6d4c057
flame: removing default preset
jakubjezek001 May 26, 2022
642391b
Merge branch 'develop' into bugfix/OP-3191_Flame-publishing-bugs
jakubjezek001 May 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 200 additions & 15 deletions openpype/hosts/flame/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
import json
import pickle
import clique
import tempfile
import itertools
import contextlib
Expand Down Expand Up @@ -560,7 +561,7 @@ def get_segment_attributes(segment):
if not hasattr(segment, attr_name):
continue
attr = getattr(segment, attr_name)
segment_attrs_data[attr] = str(attr).replace("+", ":")
segment_attrs_data[attr_name] = str(attr).replace("+", ":")

if attr_name in ["record_in", "record_out"]:
clip_data[attr_name] = attr.relative_frame
Expand Down Expand Up @@ -762,6 +763,7 @@ class MediaInfoFile(object):
_start_frame = None
_fps = None
_drop_mode = None
_file_pattern = None

def __init__(self, path, **kwargs):

Expand All @@ -773,17 +775,28 @@ def __init__(self, path, **kwargs):
self._validate_media_script_path()

# derivate other feed variables
self.feed_basename = os.path.basename(path)
self.feed_dir = os.path.dirname(path)
self.feed_ext = os.path.splitext(self.feed_basename)[1][1:].lower()
feed_basename = os.path.basename(path)
feed_dir = os.path.dirname(path)
feed_ext = os.path.splitext(feed_basename)[1][1:].lower()

with maintained_temp_file_path(".clip") as tmp_path:
self.log.info("Temp File: {}".format(tmp_path))
self._generate_media_info_file(tmp_path)
self._generate_media_info_file(tmp_path, feed_ext, feed_dir)

# get collection containing feed_basename from path
self.file_pattern = self._get_collection(
feed_basename, feed_dir, feed_ext)

if (
not self.file_pattern
and os.path.exists(os.path.join(feed_dir, feed_basename))
):
self.file_pattern = feed_basename

# get clip data and make them single if there is multiple
# clips data
xml_data = self._make_single_clip_media_info(tmp_path)
xml_data = self._make_single_clip_media_info(
tmp_path, feed_basename, self.file_pattern)
self.log.debug("xml_data: {}".format(xml_data))
self.log.debug("type: {}".format(type(xml_data)))

Expand All @@ -794,6 +807,123 @@ def __init__(self, path, **kwargs):
self.log.debug("drop frame: {}".format(self.drop_mode))
self.clip_data = xml_data

def _get_collection(self, feed_basename, feed_dir, feed_ext):
""" Get collection string

Args:
feed_basename (str): file base name
feed_dir (str): file's directory
feed_ext (str): file extension

Raises:
AttributeError: feed_ext is not matching feed_basename

Returns:
str: collection basename with range of sequence
"""
partialname = self._separate_file_head(feed_basename, feed_ext)
self.log.debug("__ partialname: {}".format(partialname))

# make sure partial input basename is having correct extensoon
if not partialname:
raise AttributeError(
"Wrong input attributes. Basename - {}, Ext - {}".format(
feed_basename, feed_ext
)
)

# get all related files
files = [
f for f in os.listdir(feed_dir)
if partialname == self._separate_file_head(f, feed_ext)
]

# ignore reminders as we dont need them
collections = clique.assemble(files)[0]

# in case no collection found return None
# it is probably just single file
if not collections:
return

# we expect only one collection
collection = collections[0]

self.log.debug("__ collection: {}".format(collection))

if collection.is_contiguous():
return self._format_collection(collection)

# add `[` in front to make sure it want capture
# shot name with the same number
number_from_path = self._separate_number(feed_basename, feed_ext)
search_number_pattern = "[" + number_from_path
# convert to multiple collections
_continues_colls = collection.separate()
for _coll in _continues_colls:
coll_to_text = self._format_collection(
_coll, len(number_from_path))
self.log.debug("__ coll_to_text: {}".format(coll_to_text))
if search_number_pattern in coll_to_text:
return coll_to_text

@staticmethod
def _format_collection(collection, padding=None):
padding = padding or collection.padding
# if no holes then return collection
head = collection.format("{head}")
tail = collection.format("{tail}")
range_template = "[{{:0{0}d}}-{{:0{0}d}}]".format(
padding)
ranges = range_template.format(
min(collection.indexes),
max(collection.indexes)
)
# if no holes then return collection
return "{}{}{}".format(head, ranges, tail)

def _separate_file_head(self, basename, extension):
""" Get only head with out sequence and extension

Args:
basename (str): file base name
extension (str): file extension

Returns:
str: file head
"""
# in case sequence file
found = re.findall(
r"(.*)[._][\d]*(?=.{})".format(extension),
basename,
)
if found:
return found.pop()

# in case single file
name, ext = os.path.splitext(basename)

if extension == ext[1:]:
return name

def _separate_number(self, basename, extension):
""" Get only sequence number as string

Args:
basename (str): file base name
extension (str): file extension

Returns:
str: number with padding
"""
# in case sequence file
found = re.findall(
r"[._]([\d]*)(?=.{})".format(extension),
basename,
)
if found:
return found.pop()

@property
def clip_data(self):
"""Clip's xml clip data
Expand Down Expand Up @@ -846,18 +976,41 @@ def drop_mode(self):
def drop_mode(self, text):
self._drop_mode = str(text)

@property
def file_pattern(self):
"""Clips file patter

Returns:
str: file pattern. ex. file.[1-2].exr
"""
return self._file_pattern

@file_pattern.setter
def file_pattern(self, fpattern):
self._file_pattern = fpattern

def _validate_media_script_path(self):
if not os.path.isfile(self.MEDIA_SCRIPT_PATH):
raise IOError("Media Scirpt does not exist: `{}`".format(
self.MEDIA_SCRIPT_PATH))

def _generate_media_info_file(self, fpath):
def _generate_media_info_file(self, fpath, feed_ext, feed_dir):
""" Generate media info xml .clip file

Args:
fpath (str): .clip file path
feed_ext (str): file extension to be filtered
feed_dir (str): look up directory

Raises:
TypeError: Type error if it fails
"""
# Create cmd arguments for gettig xml file info file
cmd_args = [
self.MEDIA_SCRIPT_PATH,
"-e", self.feed_ext,
"-e", feed_ext,
"-o", fpath,
self.feed_dir
feed_dir
]

try:
Expand All @@ -867,7 +1020,20 @@ def _generate_media_info_file(self, fpath):
raise TypeError(
"Error creating `{}` due: {}".format(fpath, error))

def _make_single_clip_media_info(self, fpath):
def _make_single_clip_media_info(self, fpath, feed_basename, path_pattern):
""" Separate only relative clip object form .clip file

Args:
fpath (str): clip file path
feed_basename (str): search basename
path_pattern (str): search file pattern (file.[1-2].exr)

Raises:
ET.ParseError: if nothing found

Returns:
ET.Element: xml element data of matching clip
"""
with open(fpath) as f:
lines = f.readlines()
_added_root = itertools.chain(
Expand All @@ -878,14 +1044,30 @@ def _make_single_clip_media_info(self, fpath):
xml_clips = new_root.findall("clip")
matching_clip = None
for xml_clip in xml_clips:
if xml_clip.find("name").text in self.feed_basename:
matching_clip = xml_clip
clip_name = xml_clip.find("name").text
self.log.debug("__ clip_name: `{}`".format(clip_name))
if clip_name not in feed_basename:
continue

# test path pattern
for out_track in xml_clip.iter("track"):
for out_feed in out_track.iter("feed"):
for span in out_feed.iter("span"):
# start frame
span_path = span.find("path")
self.log.debug(
"__ span_path.text: {}, path_pattern: {}".format(
span_path.text, path_pattern
)
)
if path_pattern in span_path.text:
matching_clip = xml_clip

if matching_clip is None:
# return warning there is missing clip
raise ET.ParseError(
"Missing clip in `{}`. Available clips {}".format(
self.feed_basename, [
feed_basename, [
xml_clip.find("name").text
for xml_clip in xml_clips
]
Expand All @@ -894,6 +1076,11 @@ def _make_single_clip_media_info(self, fpath):
return matching_clip

def _get_time_info_from_origin(self, xml_data):
"""Set time info to class attributes

Args:
xml_data (ET.Element): clip data
"""
try:
for out_track in xml_data.iter('track'):
for out_feed in out_track.iter('feed'):
Expand All @@ -912,8 +1099,6 @@ def _get_time_info_from_origin(self, xml_data):
'startTimecode/dropMode')
self.drop_mode = out_feed_drop_mode_obj.text
break
else:
continue
except Exception as msg:
self.log.warning(msg)

Expand Down
3 changes: 3 additions & 0 deletions openpype/hosts/flame/api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ class PublishableClip:
driving_layer_default = ""
index_from_segment_default = False
use_shot_name_default = False
include_handles_default = False

def __init__(self, segment, **kwargs):
self.rename_index = kwargs["rename_index"]
Expand Down Expand Up @@ -493,6 +494,8 @@ def _populate_attributes(self):
"reviewTrack", {}).get("value") or self.review_track_default
self.audio = self.ui_inputs.get(
"audio", {}).get("value") or False
self.include_handles = self.ui_inputs.get(
"includeHandles", {}).get("value") or self.include_handles_default

# build subset name from layer name
if self.subset_name == "[ track name ]":
Expand Down
41 changes: 37 additions & 4 deletions openpype/hosts/flame/api/render_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import os
from xml.etree import ElementTree as ET
import openpype.api as openpype

log = openpype.Logger.get_logger(__name__)
jakubjezek001 marked this conversation as resolved.
Show resolved Hide resolved


def export_clip(export_path, clip, preset_path, **kwargs):
Expand Down Expand Up @@ -143,10 +146,40 @@ def modify_preset_file(xml_path, staging_dir, data):

# change xml following data keys
with open(xml_path, "r") as datafile:
tree = ET.parse(datafile)
_root = ET.parse(datafile)

for key, value in data.items():
for element in tree.findall(".//{}".format(key)):
element.text = str(value)
tree.write(temp_path)
try:
if "/" in key:
if not key.startswith("./"):
key = ".//" + key

split_key_path = key.split("/")
element_key = split_key_path[-1]
parent_obj_path = "/".join(split_key_path[:-1])

parent_obj = _root.find(parent_obj_path)
element_obj = parent_obj.find(element_key)
if not element_obj:
append_element(parent_obj, element_key, value)
else:
finds = _root.findall(".//{}".format(key))
if not finds:
raise AttributeError
for element in finds:
element.text = str(value)
except AttributeError:
log.warning(
"Cannot create attribute: {}: {}. Skipping".format(
key, value
))
_root.write(temp_path)

return temp_path


def append_element(root_element_obj, key, value):
new_element_obj = ET.Element(key)
log.debug("__ new_element_obj: {}".format(new_element_obj))
new_element_obj.text = str(value)
root_element_obj.insert(0, new_element_obj)
Loading