Skip to content
Open
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
72c2f1e
wip for creator, collector and extractor for editorial product type
moonyuet Oct 10, 2024
ef4e87d
remove collect editorial as it is not gonna use for this workflow
moonyuet Oct 10, 2024
9f24405
remove otio-related workflow as it is not related to this PR
moonyuet Oct 10, 2024
f96b691
wip the creator and render for clip function
moonyuet Oct 11, 2024
bbfafef
wip the creator
moonyuet Oct 11, 2024
58e46bf
wip on the creator and collector
moonyuet Oct 14, 2024
b6082c4
wip on the creator
moonyuet Oct 14, 2024
427828e
use editorial pkg product type
moonyuet Oct 15, 2024
f4a6956
remove to return unnecessary function
moonyuet Oct 15, 2024
4962722
wip on implementation
moonyuet Oct 15, 2024
ea40c2d
draft the otio_unreal_export script
moonyuet Oct 31, 2024
9377c8d
draft the otio_unreal_export script
moonyuet Oct 31, 2024
47dd36a
resolve conflict
moonyuet Nov 1, 2024
3001478
wip creator
moonyuet Nov 1, 2024
521d94b
wip creator
moonyuet Nov 1, 2024
1e60e01
add intermediate renders and supports rendering for editorial package
moonyuet Nov 4, 2024
4864345
add the check on the publish error in the collector if the users do n…
moonyuet Nov 4, 2024
306cd6e
make sure the frame range is correct
moonyuet Nov 4, 2024
6f93a9c
edit rendering py for rendering out the image in different directory
moonyuet Nov 4, 2024
c6afe1e
fix the enumerate value
moonyuet Nov 4, 2024
be237a5
update the intermediate render product type as editorial publish and …
moonyuet Nov 5, 2024
2cbab6e
edit the unreal_export.py
moonyuet Nov 5, 2024
b146626
coverting otio logic to accompany wioth unreal in unreal_export.py
moonyuet Nov 5, 2024
9291eaa
coverting otio logic to accompany wioth unreal in unreal_export.py
moonyuet Nov 5, 2024
78d794e
implement unreal logic into unreal_export.py
moonyuet Nov 6, 2024
beb46a3
impelement the extractor for intermediate render
moonyuet Nov 7, 2024
fd08023
implement pre-launch hook for otio installation
moonyuet Nov 8, 2024
adf1d84
implement extract edidtorial package.py
moonyuet Nov 8, 2024
454c941
make sure the opentimelineio is using 0.16.0
moonyuet Nov 8, 2024
aa662db
edit the unreal export.py for getting correct track name
moonyuet Nov 8, 2024
726e169
update the extract data for the representation
moonyuet Nov 8, 2024
8e5a726
add remove tags
moonyuet Nov 8, 2024
90a08c9
add remove tags
moonyuet Nov 8, 2024
b08b410
ruff cosmetic fix
moonyuet Nov 8, 2024
f5a6ce1
uses get_name instead of get_sequence().get_name()
moonyuet Nov 11, 2024
ac16030
uses get_name instead of get_sequence().get_name()
moonyuet Nov 11, 2024
403cf56
resolve conflict
moonyuet Nov 13, 2024
aa61db2
make sure the image sequences not being rendered per sub sequence dur…
moonyuet Nov 13, 2024
afebb9c
rename the collector and name of the hook for otio according to Jeza'…
moonyuet Feb 18, 2025
ba81eff
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
jakubjezek001 Jun 17, 2025
88f3e04
make sure editorial package published successfully
moonyuet Jun 23, 2025
8fd04af
Add MovieSceneSubTrack as TRACK_TYPES
moonyuet Jun 27, 2025
d7a9519
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
moonyuet Jun 27, 2025
0c86f21
Add condition check on getting sequence shot name as track name
moonyuet Jun 30, 2025
e0eb3d5
use sequence name instead
moonyuet Jun 30, 2025
de5418d
check if the section is MovieSceneCInematicShotTrack ifnot it will us…
moonyuet Jun 30, 2025
53ee6a8
implement the condition check on the section in create_otio_clip
moonyuet Jul 2, 2025
bc02d20
update the rendering.py and unreaal_export to clarify the shot name a…
moonyuet Jul 23, 2025
d04e2d7
Merge remote-tracking branch 'origin/develop' into feature/AY-6916_Ed…
antirotor Jul 23, 2025
74973af
make sure using render publish path for target_url
moonyuet Jul 29, 2025
a8aaa39
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
moonyuet Jul 29, 2025
6c7e2de
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
moonyuet Jul 29, 2025
5538584
Merge branch 'feature/AY-6916_Editorial-publish-from-Unreal-to-Ayon' …
moonyuet Jul 29, 2025
f03543c
update the otio data and render setting for editorial publish
moonyuet Jul 30, 2025
9b256c1
resolve some unrelated content from this PR
moonyuet Jul 30, 2025
5aac81d
resolve some unrelated content from this PR
moonyuet Jul 30, 2025
9ca024e
restore and clean up some code so that the rendering should be workin…
moonyuet Jul 30, 2025
bba27dc
make sure getting the correct video mapped
moonyuet Jul 30, 2025
77d65f3
query clips as a list
moonyuet Jul 31, 2025
510e97c
make sure otio won't query the cameraMain as clips
moonyuet Jul 31, 2025
d9d88d0
dont get root template for the target url but use absolute path instead
moonyuet Jul 31, 2025
4f39c59
remove unused variable
moonyuet Jul 31, 2025
a90e360
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
moonyuet Aug 1, 2025
9331a31
introduce the rootless path back to the extract editorial package
moonyuet Aug 6, 2025
56081d0
make sure start time is correct
moonyuet Aug 8, 2025
9215364
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
antirotor Aug 11, 2025
fe26793
add validator for checking if specific review settings have been adde…
moonyuet Aug 12, 2025
c43dce7
remove unused code
moonyuet Aug 12, 2025
f5fbafa
restore the rootless path usage first and we can decide if it should …
moonyuet Aug 12, 2025
3dbf185
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
antirotor Aug 28, 2025
635dc88
wip multi exr representation for editorial
moonyuet Sep 1, 2025
b270486
publish image-sequence based otio as timeline instead
moonyuet Sep 3, 2025
ae800cc
add reviewables back to extract editorial package
moonyuet Sep 3, 2025
8ddfa51
add use_sequence options and validator to check on profile setting fo…
moonyuet Sep 4, 2025
ec1168f
align the time duration and frame start with clip if exporting otio w…
moonyuet Sep 4, 2025
a30522b
resolve the conflict and add render presets option for editorial pack…
moonyuet Sep 16, 2025
447ec7d
use relative path for target url and target url base
moonyuet Sep 16, 2025
dd2377b
Use Pathlib to make sure the path compatible to all dccs
moonyuet Sep 16, 2025
f75b082
add ffmpeg argument supports for extract intermediate representation
moonyuet Sep 22, 2025
00bab4d
remove unused import
moonyuet Sep 22, 2025
e98445f
use the correct unreal setting and fix the input arguments for ffmpeg
moonyuet Sep 22, 2025
97f750b
use different output arguments
moonyuet Sep 22, 2025
50f6f74
resolve conflict
moonyuet Sep 23, 2025
1b84edc
update the intermediate representation arguments and specific metadat…
moonyuet Sep 23, 2025
dd7e189
adding burnin as families so that to use extract burnin
moonyuet Sep 23, 2025
a354798
add burnin tags
moonyuet Sep 23, 2025
ac02bba
Merge branch 'develop' into feature/AY-6916_Editorial-publish-from-Un…
jakubjezek001 Nov 7, 2025
50399d4
Update extract_intermediate_representation.py
moonyuet Nov 25, 2025
4a52064
Update pre_otio_install.py
moonyuet Nov 25, 2025
f160e89
kuba's comment - code clean up
moonyuet Nov 26, 2025
0bf8c68
ruff fix
moonyuet Nov 26, 2025
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
42 changes: 41 additions & 1 deletion client/ayon_unreal/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
)
from ayon_unreal.api.pipeline import (
get_camera_tracks,
ls
ls,
UNREAL_VERSION
)
from ayon_core.pipeline.context_tools import get_current_folder_entity
import ayon_api
Expand Down Expand Up @@ -306,3 +307,42 @@ def import_animation(
sequence.get_playback_end())
sec_params = section.get_editor_property('params')
sec_params.set_editor_property('animation', animation)


def get_shot_track_names(sel_objects=None, get_name=True):
selection = [
a for a in sel_objects
if a.get_class().get_name() == "LevelSequence"
]
if (
UNREAL_VERSION.major == 5
and UNREAL_VERSION.minor > 4
):
sub_sequence_tracks = [
track for sel in selection for track in
sel.find_tracks_by_type(unreal.MovieSceneSubTrack)
]
else:
sub_sequence_tracks = [
track for sel in selection for track in
sel.find_master_tracks_by_type(unreal.MovieSceneSubTrack)
]

if get_name:
return [shot_tracks.get_display_name() for shot_tracks in
sub_sequence_tracks]
else:
return [shot_tracks for shot_tracks in sub_sequence_tracks]


def get_shot_tracks(members):
ar = unreal.AssetRegistryHelpers.get_asset_registry()
selected_sequences = [
ar.get_asset_by_object_path(member).get_asset() for member in members
]
return get_shot_track_names(selected_sequences, get_name=False)


def get_screen_resolution():
game_user_settings = unreal.GameUserSettings.get_game_user_settings()
return game_user_settings.get_screen_resolution()
58 changes: 57 additions & 1 deletion client/ayon_unreal/api/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,30 @@ def get_subsequences(sequence: unreal.LevelSequence):
return []


def get_movie_shot_tracks(sequence: unreal.LevelSequence):
"""Get list of movie shot tracks from sequence.

Args:
sequence (unreal.LevelSequence): Sequence

Returns:
list(unreal.LevelSequence): List of movie shot tracks

"""
tracks = sequence.find_master_tracks_by_type(unreal.MovieSceneSubTrack)
subscene_track = next(
(
t
for t in tracks
if t.get_class() == unreal.MovieSceneCinematicShotTrack.static_class()
),
None,
)
if subscene_track is not None and subscene_track.get_sections():
return subscene_track.get_sections()
return []


def set_sequence_hierarchy(
seq_i, seq_j, max_frame_i, min_frame_j, max_frame_j, map_paths
):
Expand Down Expand Up @@ -1000,7 +1024,7 @@ def get_sequence(files):
Optional[list[str]]: file sequence.

"""
collections, _remainder = clique.assemble(
collections, _ = clique.assemble(
files,
patterns=[clique.PATTERNS["frames"]],
minimum_items=1)
Expand All @@ -1013,6 +1037,38 @@ def get_sequence(files):
return [os.path.basename(filename) for filename in collections[0]]


def get_sequence_for_otio(files):
"""Get sequence from filename.

This will only return files if they exist on disk as it tries
to collect the sequence using the filename pattern and searching
for them on disk.

Supports negative frame ranges like -001, 0000, 0001 and -0001,
0000, 0001.

Arguments:
files (str): List of files

Returns:
Optional[list[str]]: file sequence.
Optional[str]: file head.

"""
base_filenames = [os.path.basename(filename) for filename in files]
collections, _remainder = clique.assemble(
base_filenames,
patterns=[clique.PATTERNS["frames"]],
minimum_items=1)

if len(collections) > 1:
raise ValueError(
f"Multiple collections found for {collections}. "
"This is a bug.")
filename_padding = collections[0].padding
return filename_padding


def find_camera_actors_in_camera_tracks(sequence) -> list[Any]:
"""Find the camera actors in the tracks from the Level Sequence

Expand Down
30 changes: 25 additions & 5 deletions client/ayon_unreal/api/rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def start_rendering():

for i in instances:
data = pipeline.parse_container(i.get_path_name())
if data["productType"] == "render":
if data["productType"] == "render" or "editorial_pkg":
inst_data.append(data)

try:
Expand Down Expand Up @@ -199,6 +199,8 @@ def start_rendering():
current_level_name = current_level.get_outer().get_path_name()

for i in inst_data:
if i["productType"] == "editorial_pkg":
render_dir = f"{root}/{project_name}/editorial_pkg"
# for some reason the instance data has strings, convert them
# back to their original types
render_preset = ast.literal_eval(i["creator_attributes"]).get(
Expand Down Expand Up @@ -226,7 +228,7 @@ def start_rendering():
for seq in sequences:
subscenes = pipeline.get_subsequences(seq.get('sequence'))

if subscenes:
if subscenes and i["productType"] != "editorial_pkg":
sequences.extend(
{
"sequence": sub_seq.get_sequence(),
Expand All @@ -241,6 +243,24 @@ def start_rendering():
}
for sub_seq in subscenes
)
# remove all the codes unnecssary for the editorial package
elif subscenes:
for sub_seq in subscenes:
sub_seq_obj = sub_seq.get_sequence()
if sub_seq_obj is None:
continue
# exclude camera-related sequence
elif "_camera" in sub_seq_obj.get_name():
continue
render_list.append({
"sequence": seq.get('sequence'),
"output": (f"{seq.get('output')}"),
"frame_range": (
sub_seq.get_start_frame(),
sub_seq.get_end_frame(),
)
}
)
elif "_camera" not in seq.get('sequence').get_name():
render_list.append(seq)

Expand Down Expand Up @@ -269,8 +289,7 @@ def start_rendering():
# read in the job's OnJobFinished callback. We could,
# for instance, pass the AyonPublishInstance's path to the job.
# job.user_data = ""

output_dir = render_setting.get('output')
output_name = render_setting.get('output')
shot_name = render_setting.get('sequence').get_name()

settings = job_config.find_or_add_setting_by_class(
Expand All @@ -279,8 +298,9 @@ def start_rendering():
settings.custom_start_frame = render_setting.get("frame_range")[0]
settings.custom_end_frame = render_setting.get("frame_range")[1]
settings.use_custom_playback_range = True
# make sure all sequences share the same filename
settings.file_name_format = f"{shot_name}" + ".{frame_number}"
settings.output_directory.path = f"{render_dir}/{output_dir}"
settings.output_directory.path = f"{render_dir}/{output_name}"

job_config.find_or_add_setting_by_class(
unreal.MoviePipelineDeferredPassBase)
Expand Down
Loading