Skip to content

Commit cc1aac7

Browse files
runeganmarkreidvfx
andauthored
Update to work on U5.5 (#4)
* Replace deprecated methods clip_if and children_if have been deprecated in latest otio schema.track was also removed Signed-off-by: Mark Reid <[email protected]> * Prevent sending None to load_or_create_level_seq exception is aready caught in get_sub_sequence_path Signed-off-by: Mark Reid <[email protected]> * Only select standard frame rates, and support for fractional rates like 23.976, 29.97 and 59.94 Signed-off-by: Mark Reid <[email protected]> * Handle case where sub_seq could be None Signed-off-by: Mark Reid <[email protected]> * timeline.find_clip -> timeline.find_clips Signed-off-by: runegan <[email protected]> * Remove reference to master track and replace with track master_track functions are depracted, we should use just track Signed-off-by: runegan <[email protected]> * fix time_scale for UE5.5 UE5.5 uses a MovieSceneTimeWarpVariant. We must convert from this or to this when getting/setting Signed-off-by: runegan <[email protected]> * Keep track of lock state in writable state Previously this would always lock all shots. Signed-off-by: runegan <[email protected]> * Replace get_marked_frames with get_marked_frames_from_sequence get_marked_frames is depracted Signed-off-by: runegan <[email protected]> * replace Track.Kind with Track.Kind Signed-off-by: runegan <[email protected]> --------- Signed-off-by: Mark Reid <[email protected]> Signed-off-by: runegan <[email protected]> Co-authored-by: Mark Reid <[email protected]>
1 parent c8fb4ec commit cc1aac7

File tree

5 files changed

+64
-18
lines changed

5 files changed

+64
-18
lines changed

OpenTimelineIOUtilities/Content/Python/otio_unreal/adapter.py

100644100755
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def import_otio(
6464
# items (stacks and clips) to sub-sequences.
6565
run_pre_import_otio_item_hook(timeline.tracks)
6666

67-
for item in timeline.children_if():
67+
for item in timeline.find_children():
6868
if isinstance(item, (otio.schema.Stack, otio.schema.Clip)):
6969
run_pre_import_otio_item_hook(item)
7070

@@ -127,7 +127,7 @@ def export_otio(filepath, level_seq, dry_run=False):
127127
# map unreal metadata to rendered outputs.
128128
timeline = run_post_export_otio_hook(timeline)
129129

130-
for clip in timeline.clip_if():
130+
for clip in timeline.find_clips():
131131
# Implementation-defined clip update to inject a media reference
132132
# that maps unreal metadata to a rendered output.
133133
run_post_export_otio_clip_hook(clip)

OpenTimelineIOUtilities/Content/Python/otio_unreal/level_sequence.py

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,21 @@ def writable(self):
4747
is_read_only = self.level_seq.is_read_only()
4848
self.level_seq.set_read_only(False)
4949

50+
section_status = []
5051
# Unlock shot tracks
5152
shot_track = self.get_shot_track()
5253
if shot_track is not None:
5354
for section in shot_track.get_sections():
55+
section_status.append(section.is_locked())
5456
section.set_is_locked(False)
5557

5658
yield
5759

5860
# Lock all shot tracks
5961
shot_track = self.get_shot_track()
6062
if shot_track is not None:
61-
for section in shot_track.get_sections():
62-
section.set_is_locked(True)
63+
for section, lock_state in zip(shot_track.get_sections(), section_status):
64+
section.set_is_locked(lock_state)
6365

6466
# Restore level sequence read-only state
6567
self.level_seq.set_read_only(is_read_only)
@@ -73,7 +75,7 @@ def get_shot_track(self):
7375
unreal.MovieSceneCinematicShotTrack: Shot track, if found,
7476
otherwise None.
7577
"""
76-
shot_tracks = self.level_seq.find_master_tracks_by_exact_type(
78+
shot_tracks = self.level_seq.find_tracks_by_exact_type(
7779
unreal.MovieSceneCinematicShotTrack
7880
)
7981
if shot_tracks:
@@ -91,15 +93,49 @@ def get_frame_rate(self):
9193

9294
return float(display_rate.numerator) / float(display_rate.denominator)
9395

96+
def get_nearest_rate(self, frame_rate):
97+
"""Convert a float frame rate to an exact fraction
98+
Args:
99+
frame_rate (float): Frames per second
100+
"""
101+
# rates are from the sequencer display rate menu
102+
rates = ((12, 1),
103+
(15, 1),
104+
(24000, 1001),
105+
(24, 1),
106+
(25, 1),
107+
(30000, 1001),
108+
(30, 1),
109+
(48, 1),
110+
(60000, 1001),
111+
(50, 1),
112+
(60, 1),
113+
(100, 1),
114+
(120, 1),
115+
(240, 1))
116+
117+
nearest = None
118+
min_diff = float('inf')
119+
for i, (num, den) in enumerate(rates):
120+
valid_rate = float(num)/float(den)
121+
if frame_rate == valid_rate:
122+
return unreal.FrameRate(numerator=num, denominator=den)
123+
124+
diff = abs(frame_rate - valid_rate)
125+
if (diff >= min_diff):
126+
continue
127+
min_diff = diff
128+
nearest = [num, den]
129+
130+
return unreal.FrameRate(numerator=nearest[0], denominator=nearest[1])
131+
94132
def set_frame_rate(self, frame_rate):
95133
"""Set frame rate (frames per second).
96134
97135
Args:
98136
frame_rate (float): Frames per second
99137
"""
100-
self.level_seq.set_display_rate(
101-
unreal.FrameRate(numerator=frame_rate, denominator=1)
102-
)
138+
self.level_seq.set_display_rate(self.get_nearest_rate(frame_rate))
103139

104140
def get_ticks_per_frame(self):
105141
"""Calculate ticks per frame.
@@ -280,7 +316,7 @@ def update_markers(self, parent_item):
280316
if parent_item.markers:
281317
parent_item.markers.clear()
282318

283-
for frame_marker in self.level_seq.get_marked_frames():
319+
for frame_marker in self.level_seq.get_marked_frames_from_sequence():
284320
# Convert from frame number at tick resolution
285321
frame = frame_marker.frame_number.value // self.get_ticks_per_frame()
286322
marked_range = TimeRange(
@@ -377,7 +413,7 @@ def update_stack(self, parent_stack):
377413
multi_track = len(row_sections) > 1
378414

379415
for row_idx, sections in sorted(row_sections.items()):
380-
video_track = otio.schema.Track(kind=otio.schema.track.TrackKind.Video)
416+
video_track = otio.schema.Track(kind=otio.schema.Track.Kind.Video)
381417

382418
# Name track if possible
383419
if not multi_track:
@@ -489,7 +525,7 @@ def update_from_stack(self, parent_stack):
489525
shot_track = self.get_shot_track()
490526

491527
if shot_track is None:
492-
shot_track = self.level_seq.add_master_track(
528+
shot_track = self.level_seq.add_track(
493529
unreal.MovieSceneCinematicShotTrack
494530
)
495531

@@ -509,7 +545,7 @@ def update_from_stack(self, parent_stack):
509545
# Video tracks are stacked in reverse in a timeline, with the lowest
510546
# index at the bottom.
511547
for row_index, track in enumerate(reversed(parent_stack)):
512-
if track.kind != otio.schema.track.TrackKind.Video:
548+
if track.kind != otio.schema.TrackKind.Video:
513549
continue
514550

515551
# Name track if possible
@@ -525,9 +561,8 @@ def update_from_stack(self, parent_stack):
525561
continue
526562

527563
# Clip or Stack: Update or create section
528-
try:
529-
sub_seq_path = get_sub_sequence_path(item)
530-
except KeyError:
564+
sub_seq_path = get_sub_sequence_path(item)
565+
if not sub_seq_path:
531566
continue
532567

533568
if (
@@ -540,10 +575,15 @@ def update_from_stack(self, parent_stack):
540575
sub_seq = section.get_sequence()
541576
else:
542577
sub_seq = load_or_create_level_seq(sub_seq_path)
578+
if not sub_seq:
579+
continue
543580

544581
section = shot_track.add_section()
545582
section.set_sequence(sub_seq)
546583

584+
if not sub_seq:
585+
continue
586+
547587
section_proxy = ShotSectionProxy(section, self)
548588
sub_seq_proxy = LevelSequenceProxy(sub_seq, section_proxy)
549589

OpenTimelineIOUtilities/Content/Python/otio_unreal/shot_section.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ def get_time_scale(self):
5252
Returns:
5353
float: Time scalar
5454
"""
55-
return self.section.parameters.time_scale
55+
time_scale = self.section.parameters.time_scale
56+
if hasattr(unreal, 'MovieSceneTimeWarpVariant'): # UE 5.5+
57+
time_scale = time_scale.to_fixed_play_rate()
58+
return time_scale
5659

5760
def set_time_scale(self, time_scale):
5861
"""Set this section's time scale, which scales the playback
@@ -61,6 +64,9 @@ def set_time_scale(self, time_scale):
6164
Args:
6265
time_scale (float): Time scale value
6366
"""
67+
if hasattr(unreal, 'MovieSceneTimeWarpVariant'):
68+
time_scale = unreal.MovieSceneTimeWarpVariant(time_scale)
69+
6470
self.section.parameters.time_scale = time_scale
6571

6672
def get_range_in_parent(self):

OpenTimelineIOUtilities/Content/Python/otio_unreal/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def get_level_seq_references(timeline, level_seq=None):
5252

5353
level_seq_refs = [(root_level_seq_path, timeline)]
5454

55-
for item in timeline.children_if():
55+
for item in timeline.find_children():
5656
if not isinstance(item, (otio.schema.Stack, otio.schema.Clip)):
5757
continue
5858

tests/test_otio_unreal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ def test_roundtrip(self):
427427
out_timeline.tracks.metadata.clear()
428428
set_sub_sequence_path(out_timeline.tracks, root_level_seq_path)
429429

430-
for item in out_timeline.children_if():
430+
for item in out_timeline.find_children():
431431
level_seq_path = get_sub_sequence_path(item)
432432
if level_seq_path is not None:
433433

0 commit comments

Comments
 (0)