Skip to content

Commit 9fc59a5

Browse files
authored
Range in parent for transitions (#184)
* Fixed Transition support in otioview. - Added range_in_parent and trimmed_range_in_parent to Transition. - Added trim_child_range to Composition. - Added range_in_parent to Item.
1 parent 22f20fd commit 9fc59a5

File tree

5 files changed

+116
-30
lines changed

5 files changed

+116
-30
lines changed

opentimelineio/core/composition.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,10 @@ def __deepcopy__(self, md):
206206
return result
207207

208208
def _path_to_child(self, child):
209-
if not isinstance(child, item.Item):
209+
if not isinstance(child, composable.Composable):
210210
raise TypeError(
211-
"An object child of 'Item' is required, not type '{}'".format(
211+
"An object child of 'Composable' is required,"
212+
" not type '{}'".format(
212213
type(child)
213214
)
214215
)
@@ -253,8 +254,6 @@ def range_of_child(self, child, reference_space=None):
253254

254255
parents = self._path_to_child(child)
255256

256-
result_range = child.source_range
257-
258257
current = child
259258
result_range = None
260259

@@ -339,8 +338,6 @@ def trimmed_range_of_child(self, child, reference_space=None):
339338

340339
parents = self._path_to_child(child)
341340

342-
result_range = child.source_range
343-
344341
current = child
345342
result_range = None
346343

@@ -383,6 +380,34 @@ def trimmed_range_of_child(self, child, reference_space=None):
383380

384381
return opentime.TimeRange(new_start_time, new_duration)
385382

383+
def trim_child_range(self, child_range):
384+
if not self.source_range:
385+
return child_range
386+
387+
# cropped out entirely
388+
if (
389+
self.source_range.start_time >= child_range.end_time_exclusive()
390+
or self.source_range.end_time_exclusive() <= child_range.start_time
391+
):
392+
return None
393+
394+
if child_range.start_time < self.source_range.start_time:
395+
child_range = opentime.range_from_start_end_time(
396+
self.source_range.start_time,
397+
child_range.end_time_exclusive()
398+
)
399+
400+
if (
401+
child_range.end_time_exclusive() >
402+
self.source_range.end_time_exclusive()
403+
):
404+
child_range = opentime.range_from_start_end_time(
405+
child_range.start_time,
406+
self.source_range.end_time_exclusive()
407+
)
408+
409+
return child_range
410+
386411
# @{ SerializableObject override.
387412
def update(self, d):
388413
"""Like the dictionary .update() method.

opentimelineio/core/item.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ def trimmed_range_in_parent(self):
118118

119119
return self.parent().trimmed_range_of_child(self)
120120

121+
def range_in_parent(self):
122+
"""Find and return the timmed range of this item in the parent."""
123+
if not self.parent():
124+
raise exceptions.NotAChildError(
125+
"No parent of {}, cannot compute range in parent.".format(self)
126+
)
127+
128+
return self.parent().range_of_child(self)
129+
121130
def transformed_time(self, t, to_item):
122131
"""Converts time t in the coordinate system of self to coordinate
123132
system of to_item.

opentimelineio/schema/track.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,31 +92,9 @@ def range_of_child_at_index(self, index):
9292
return opentime.TimeRange(start_time, child.duration())
9393

9494
def trimmed_range_of_child_at_index(self, index, reference_space=None):
95-
range = self.range_of_child_at_index(index)
95+
child_range = self.range_of_child_at_index(index)
9696

97-
if not self.source_range:
98-
return range
99-
100-
# cropped out entirely
101-
if (
102-
self.source_range.start_time >= range.end_time_exclusive()
103-
or self.source_range.end_time_exclusive() <= range.start_time
104-
):
105-
return None
106-
107-
if range.start_time < self.source_range.start_time:
108-
range = opentime.range_from_start_end_time(
109-
self.source_range.start_time,
110-
range.end_time_exclusive()
111-
)
112-
113-
if range.end_time_exclusive() > self.source_range.end_time_exclusive():
114-
range = opentime.range_from_start_end_time(
115-
range.start_time,
116-
self.source_range.end_time_exclusive()
117-
)
118-
119-
return range
97+
return self.trim_child_range(child_range)
12098

12199
def available_range(self):
122100
durations = []

opentimelineio/schema/transition.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from .. import (
2828
opentime,
2929
core,
30+
exceptions,
3031
)
3132

3233

@@ -137,3 +138,21 @@ def overlapping():
137138

138139
def duration(self):
139140
return self.in_offset + self.out_offset
141+
142+
def range_in_parent(self):
143+
"""Find and return the range of this item in the parent."""
144+
if not self.parent():
145+
raise exceptions.NotAChildError(
146+
"No parent of {}, cannot compute range in parent.".format(self)
147+
)
148+
149+
return self.parent().range_of_child(self)
150+
151+
def trimmed_range_in_parent(self):
152+
"""Find and return the timmed range of this item in the parent."""
153+
if not self.parent():
154+
raise exceptions.NotAChildError(
155+
"No parent of {}, cannot compute range in parent.".format(self)
156+
)
157+
158+
return self.parent().trimmed_range_of_child(self)

tests/test_composition.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,61 @@ def test_repr(self):
103103
")"
104104
)
105105

106+
def test_trim_child_range(self):
107+
for st in [
108+
otio.schema.Track(name="foo"),
109+
otio.schema.Stack(name="foo")
110+
]:
111+
st.source_range = otio.opentime.TimeRange(
112+
start_time=otio.opentime.RationalTime(value=100, rate=24),
113+
duration=otio.opentime.RationalTime(value=50, rate=24)
114+
)
115+
r = otio.opentime.TimeRange(
116+
start_time=otio.opentime.RationalTime(value=110, rate=24),
117+
duration=otio.opentime.RationalTime(value=30, rate=24)
118+
)
119+
self.assertEqual(st.trim_child_range(r), r)
120+
r = otio.opentime.TimeRange(
121+
start_time=otio.opentime.RationalTime(value=0, rate=24),
122+
duration=otio.opentime.RationalTime(value=30, rate=24)
123+
)
124+
self.assertEqual(st.trim_child_range(r), None)
125+
r = otio.opentime.TimeRange(
126+
start_time=otio.opentime.RationalTime(value=1000, rate=24),
127+
duration=otio.opentime.RationalTime(value=30, rate=24)
128+
)
129+
self.assertEqual(st.trim_child_range(r), None)
130+
r = otio.opentime.TimeRange(
131+
start_time=otio.opentime.RationalTime(value=90, rate=24),
132+
duration=otio.opentime.RationalTime(value=30, rate=24)
133+
)
134+
self.assertEqual(
135+
st.trim_child_range(r),
136+
otio.opentime.TimeRange(
137+
start_time=otio.opentime.RationalTime(value=100, rate=24),
138+
duration=otio.opentime.RationalTime(value=20, rate=24)
139+
)
140+
)
141+
r = otio.opentime.TimeRange(
142+
start_time=otio.opentime.RationalTime(value=110, rate=24),
143+
duration=otio.opentime.RationalTime(value=50, rate=24)
144+
)
145+
self.assertEqual(
146+
st.trim_child_range(r),
147+
otio.opentime.TimeRange(
148+
start_time=otio.opentime.RationalTime(value=110, rate=24),
149+
duration=otio.opentime.RationalTime(value=40, rate=24)
150+
)
151+
)
152+
r = otio.opentime.TimeRange(
153+
start_time=otio.opentime.RationalTime(value=90, rate=24),
154+
duration=otio.opentime.RationalTime(value=1000, rate=24)
155+
)
156+
self.assertEqual(
157+
st.trim_child_range(r),
158+
st.source_range
159+
)
160+
106161
def test_range_of_child(self):
107162
st = otio.schema.Stack(name="foo", children=[
108163
otio.schema.Clip(

0 commit comments

Comments
 (0)