created function that splits and preserves links

This commit is contained in:
itsmattkc
2019-10-17 10:51:50 +11:00
parent 2860fe33a0
commit 276478c6d0
6 changed files with 112 additions and 8 deletions
+9
View File
@@ -235,6 +235,10 @@ void Block::Link(Block *a, Block *b)
return;
}
if (a == nullptr || b == nullptr) {
return;
}
// Assume both clips are already linked since Link() and Unlink() should be the only entry points to this array
if (a->linked_clips_.contains(b)) {
return;
@@ -259,6 +263,11 @@ void Block::Unlink(Block *a, Block *b)
b->linked_clips_.removeOne(a);
}
bool Block::AreLinked(Block *a, Block *b)
{
return a->linked_clips_.contains(b);
}
const QVector<Block*> &Block::linked_clips()
{
return linked_clips_;
+1
View File
@@ -74,6 +74,7 @@ public:
static void Link(Block* a, Block* b);
static void Link(QList<Block*> blocks);
static void Unlink(Block* a, Block* b);
static bool AreLinked(Block* a, Block* b);
const QVector<Block*>& linked_clips();
public slots:
@@ -318,6 +318,8 @@ private:
void RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps);
void SplitBlocksPreservingLinks(const QVector<Block*>& blocks, const QList<rational> &times);
void SetTimeAndSignal(const int64_t& t);
TrackOutput* GetTrackFromReference(const TrackReference& ref);
+20 -4
View File
@@ -54,15 +54,31 @@ void TimelineWidget::RazorTool::MouseRelease(TimelineViewMouseEvent *event)
// Always split at the same time
rational split_time = drag_start_.GetFrame();
QUndoCommand* command = new QUndoCommand();
QVector<Block*> blocks_to_split;
foreach (const TrackReference& track, split_tracks_) {
new TrackSplitAtTimeCommand(parent()->GetTrackFromReference(track), split_time, command);
foreach (const TrackReference& track_ref, split_tracks_) {
TrackOutput* track = parent()->GetTrackFromReference(track_ref);
Block* block_at_time = track->NearestBlockBefore(split_time);
// Ensure there's a valid block here
if (block_at_time != track
&& !blocks_to_split.contains(block_at_time)) {
blocks_to_split.append(block_at_time);
// Add links if no alt is held
if (!(event->GetModifiers() & Qt::AltModifier)) {
foreach (Block* link, block_at_time->linked_clips()) {
if (!blocks_to_split.contains(link)) {
blocks_to_split.append(link);
}
}
}
}
}
split_tracks_.clear();
olive::undo_stack.pushIfHasChildren(command);
olive::undo_stack.push(new BlockSplitPreservingLinksCommand(blocks_to_split, {split_time}));
dragging_ = false;
}
+68 -4
View File
@@ -32,12 +32,25 @@ Block* CreateSplitBlock(Block* block, rational point, QObject* parent = nullptr)
return copy;
}
Node* TakeNodeFromParentGraph(Node* n, QObject* new_parent = nullptr) {
Node* TakeNodeFromParentGraph(Node* n, QObject* new_parent = nullptr)
{
static_cast<NodeGraph*>(n->parent())->TakeNode(n, new_parent);
return n;
}
TrackOutput* TrackFromBlock(Block* b)
{
Block* next = b->next();
do {
next = b->next();
} while (next != nullptr && next->type() != Block::kEnd);
// A little hacky, but this should either be a TrackOutput* or nullptr
return static_cast<TrackOutput*>(next);
}
BlockResizeCommand::BlockResizeCommand(Block *block, rational new_length, QUndoCommand* parent) :
QUndoCommand(parent),
block_(block),
@@ -387,13 +400,16 @@ void BlockSplitCommand::undo()
track_->UnblockInvalidateCache();
}
Block *BlockSplitCommand::new_block()
{
return new_block_;
}
TrackSplitAtTimeCommand::TrackSplitAtTimeCommand(TrackOutput *track, rational point, QUndoCommand *parent) :
QUndoCommand(parent)
{
// Find Block that contains this time
for (int i=0;i<track->Blocks().size();i++) {
Block* b = track->Blocks().at(i);
foreach (Block* b, track->Blocks()) {
if (b->out() == point) {
// This time is between blocks, no split needs to occur
return;
@@ -439,3 +455,51 @@ void TrackPrependBlockCommand::undo()
{
track_->RippleRemoveBlock(block_);
}
BlockSplitPreservingLinksCommand::BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational> &times, QUndoCommand *parent) :
QUndoCommand(parent),
blocks_(blocks),
times_(times)
{
QVector< QVector<Block*> > split_blocks(times.size());
for (int i=0;i<times.size();i++) {
const rational& time = times.at(i);
QVector<Block*> splits(blocks.size());
for (int j=0;j<blocks.size();j++) {
Block* b = blocks.at(j);
if (b->in() < time && b->out() > time) {
BlockSplitCommand* split_command = new BlockSplitCommand(TrackFromBlock(b), b, time, this);
splits.replace(j, split_command->new_block());
} else {
splits.replace(j, nullptr);
}
}
split_blocks.replace(i, splits);
}
// Now that we've determined all the splits, we can relink everything
for (int i=0;i<blocks_.size();i++) {
Block* a = blocks.at(i);
for (int j=0;j<blocks.size();j++) {
if (i == j) {
continue;
}
Block* b = blocks.at(j);
if (Block::AreLinked(a, b)) {
// These blocks are linked, ensure all the splits are linked too
foreach (const QVector<Block*>& split_list, split_blocks) {
Block::Link(split_list.at(i), split_list.at(j));
}
}
}
}
}
+12
View File
@@ -179,6 +179,8 @@ public:
virtual void redo() override;
virtual void undo() override;
Block* new_block();
private:
TrackOutput* track_;
Block* block_;
@@ -196,6 +198,16 @@ public:
TrackSplitAtTimeCommand(TrackOutput* track, rational point, QUndoCommand* parent = nullptr);
};
class BlockSplitPreservingLinksCommand : public QUndoCommand {
public:
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times, QUndoCommand* parent = nullptr);
private:
QVector<Block *> blocks_;
QList<rational> times_;
};
/**
* @brief Replaces Block `old` with Block `replace`
*