diff --git a/app/task/project/loadotio/loadotio.cpp b/app/task/project/loadotio/loadotio.cpp index 240b19a69..c7510939d 100644 --- a/app/task/project/loadotio/loadotio.cpp +++ b/app/task/project/loadotio/loadotio.cpp @@ -27,10 +27,12 @@ #include #include #include +#include #include #include "node/block/clip/clip.h" #include "node/block/gap/gap.h" +#include "node/block/transition/crossdissolve/crossdissolvetransition.h" #include "node/project/folder/folder.h" #include "node/project/footage/footage.h" #include "node/project/sequence/sequence.h" @@ -82,13 +84,16 @@ bool LoadOTIOTask::Run() QMap imported_footage; foreach (auto timeline, timelines) { + // Create sequence Sequence* sequence = new Sequence(); sequence->SetLabel(QString::fromStdString(timeline->name())); - sequence->setParent(project_->root()); + sequence->setParent(project_); + FolderAddChild(project_->root(), sequence).redo(); // FIXME: As far as I know, OTIO doesn't store video/audio parameters? sequence->set_default_parameters(); + // Iterate through tracks for (auto c : timeline->tracks()->children()) { auto otio_track = static_cast(c.value); @@ -105,6 +110,7 @@ bool LoadOTIOTask::Run() type = Track::kAudio; } + // Create track TimelineAddTrackCommand t(sequence->track_list(type)); t.redo(); track = t.track(); @@ -120,6 +126,9 @@ bool LoadOTIOTask::Run() return false; } + Block* previous_block = nullptr; + bool prev_block_transition = false; + for (auto otio_block_retainer : clip_map) { auto otio_block = otio_block_retainer.value; @@ -134,27 +143,67 @@ bool LoadOTIOTask::Run() block = new GapBlock(); + } else if (otio_block->schema_name() == "Transition") { + + // Todo: Look into OTIO supported transitions and add them to Olive + block = new CrossDissolveTransition(); + } else { // We don't know what this is yet, just create a gap for now so that *something* is there qWarning() << "Found unknown block type:" << otio_block->schema_name().c_str(); block = new GapBlock(); - } + block->setParent(project_); block->SetLabel(QString::fromStdString(otio_block->name())); - rational start_time = rational::fromDouble(static_cast(otio_block)->source_range()->start_time().to_seconds()); - rational duration = rational::fromDouble(static_cast(otio_block)->source_range()->duration().to_seconds()); - - block->set_media_in(start_time); - block->set_length_and_media_out(duration); - block->setParent(sequence); track->AppendBlock(block); + rational start_time; + rational duration; + + if (otio_block->schema_name() == "Clip" || otio_block->schema_name() == "Gap") { + start_time = + rational::fromDouble(static_cast(otio_block)->source_range()->start_time().to_seconds()); + duration = + rational::fromDouble(static_cast(otio_block)->source_range()->duration().to_seconds()); + + block->set_media_in(start_time); + block->set_length_and_media_out(duration); + } + + // If the previous block was a transition, connect the current block to it + if (prev_block_transition) { + TransitionBlock* previous_transition_block = static_cast(previous_block); + Node::ConnectEdge(block, NodeInput(previous_transition_block, TransitionBlock::kInBlockInput)); + prev_block_transition = false; + } + + if (otio_block->schema_name() == "Transition") { + TransitionBlock* transition_block = static_cast(block); + OTIO::Transition* otio_block_transition = static_cast(otio_block); + + duration = rational::fromDouble((otio_block_transition->in_offset() + otio_block_transition->out_offset()).to_seconds()); + transition_block->set_length_and_media_out(duration); + + if (previous_block) { + Node::ConnectEdge(previous_block, NodeInput(transition_block, TransitionBlock::kOutBlockInput)); + + // Set how far the transition eats into the previous clip + transition_block->set_media_in(rational::fromDouble(-otio_block_transition->out_offset().to_seconds())); + } + prev_block_transition = true; + } + + // Update this after it's used but before any continue statements + previous_block = block; + if (otio_block->schema_name() == "Clip") { auto otio_clip = static_cast(otio_block); - + if (!otio_clip->media_reference()) { + continue; + } if (otio_clip->media_reference()->schema_name() == "ExternalReference") { // Link footage QString footage_url = QString::fromStdString(static_cast(otio_clip->media_reference())->target_url()); @@ -166,7 +215,7 @@ bool LoadOTIOTask::Run() } else { probed_item = new Footage(footage_url); imported_footage.insert(footage_url, probed_item); - probed_item->setParent(project_->root()); + probed_item->setParent(project_); } Track::Reference reference;