Skip to content

Commit

Permalink
Fix for find_children() with stacks #2 (#1766)
Browse files Browse the repository at this point in the history
Signed-off-by: Darby Johnston <[email protected]>
  • Loading branch information
darbyjohnston authored Oct 10, 2024
1 parent 987d00a commit 129c4bb
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/opentimelineio/composition.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class Composition : public Item
bool shallow_search = false) const;

// Return all objects within the given search_range.
std::vector<Retainer<Composable>> children_in_range(
virtual std::vector<Retainer<Composable>> children_in_range(
TimeRange const& search_range,
ErrorStatus* error_status = nullptr) const;

Expand Down
20 changes: 20 additions & 0 deletions src/opentimelineio/stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,26 @@ Stack::range_of_all_children(ErrorStatus* error_status) const
return result;
}

std::vector<SerializableObject::Retainer<Composable>>
Stack::children_in_range(
TimeRange const& search_range,
ErrorStatus* error_status) const
{
std::vector<SerializableObject::Retainer<Composable>> children;
for (const auto& child : this->children())
{
if (const auto& item = dynamic_retainer_cast<Item>(child))
{
const auto range = item->trimmed_range_in_parent(error_status);
if (range.has_value() && range.value().intersects(search_range))
{
children.push_back(child);
}
}
}
return children;
}

TimeRange
Stack::trimmed_range_of_child_at_index(int index, ErrorStatus* error_status)
const
Expand Down
4 changes: 4 additions & 0 deletions src/opentimelineio/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class Stack : public Composition
std::map<Composable*, TimeRange>
range_of_all_children(ErrorStatus* error_status = nullptr) const override;

std::vector<Retainer<Composable>> children_in_range(
TimeRange const& search_range,
ErrorStatus* error_status = nullptr) const override;

std::optional<IMATH_NAMESPACE::Box2d>
available_image_bounds(ErrorStatus* error_status) const override;

Expand Down
58 changes: 58 additions & 0 deletions tests/test_track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,64 @@ main(int argc, char** argv)
assertEqual(result[1].value, cl1.value);
});

tests.add_test(
"test_find_children_stack", [] {
using namespace otio;

SerializableObject::Retainer<Stack> stack = new Stack();
SerializableObject::Retainer<Track> track = new Track;
SerializableObject::Retainer<Clip> clip = new Clip;
stack->append_child(track);
track->append_child(clip);

// Simple find.
clip->set_source_range(
TimeRange(RationalTime(0.0, 24.0), RationalTime(3.0, 24.0)));
otio::ErrorStatus err;
auto items = stack->find_children(
&err,
TimeRange(RationalTime(0.0, 24.0), RationalTime(1.0, 24.0)));
assertFalse(is_error(err));
assertEqual(items.size(), 2);
assertTrue(
std::find(items.begin(), items.end(), track.value) != items.end());
assertTrue(
std::find(items.begin(), items.end(), clip.value) != items.end());

// Set a short source range on the track.
track->set_source_range(
TimeRange(RationalTime(0.0, 24.0), RationalTime(2.0, 24.0)));
items = stack->find_children(
&err,
TimeRange(RationalTime(2.0, 24.0), RationalTime(1.0, 24.0)));
assertFalse(is_error(err));
assertEqual(items.size(), 0);

// Set a source range with a positive offset on the track.
track->set_source_range(
TimeRange(RationalTime(3.0, 24.0), RationalTime(3.0, 24.0)));
items = stack->find_children(
&err,
TimeRange(RationalTime(2.0, 24.0), RationalTime(1.0, 24.0)));
assertFalse(is_error(err));
assertEqual(items.size(), 1);
assertTrue(
std::find(items.begin(), items.end(), track.value) != items.end());

// Set a source range with a negative offset on the track.
track->set_source_range(
TimeRange(RationalTime(-1.0, 24.0), RationalTime(3.0, 24.0)));
items = stack->find_children(
&err,
TimeRange(RationalTime(1.0, 24.0), RationalTime(1.0, 24.0)));
assertFalse(is_error(err));
assertEqual(items.size(), 2);
assertTrue(
std::find(items.begin(), items.end(), track.value) != items.end());
assertTrue(
std::find(items.begin(), items.end(), clip.value) != items.end());
});

tests.run(argc, argv);
return 0;
}
25 changes: 25 additions & 0 deletions tests/test_track.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ def test_find_children_shallow_search(self):
self.assertEqual(result[0], cl0)
self.assertEqual(result[1], cl1)

def test_find_children_stack(self):
video_clip = otio.schema.Clip()
video_clip.source_range = otio.opentime.TimeRange(
otio.opentime.RationalTime(0.0, 30.0),
otio.opentime.RationalTime(700.0, 30.0))
audio_clip = otio.schema.Clip()
audio_clip.source_range = otio.opentime.TimeRange(
otio.opentime.RationalTime(0.0, 30.0),
otio.opentime.RationalTime(704.0, 30.0))
video_track = otio.schema.Track()
audio_track = otio.schema.Track()
stack = otio.schema.Stack()
video_track.append(video_clip)
audio_track.append(audio_clip)
stack.append(video_track)
stack.append(audio_track)

time = otio.opentime.RationalTime(703.0, 30.0)
one_frame = otio.opentime.RationalTime(1.0, 30.0)
range = otio.opentime.TimeRange(time, one_frame)
items = stack.find_children(search_range=range)
self.assertEqual(len(items), 2)
self.assertTrue(audio_clip in items)
self.assertTrue(audio_track in items)


if __name__ == '__main__':
unittest.main()

0 comments on commit 129c4bb

Please sign in to comment.