created function that splits and preserves links
This commit is contained in:
@@ -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_;
|
||||
|
||||
@@ -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> ×);
|
||||
|
||||
void SetTimeAndSignal(const int64_t& t);
|
||||
|
||||
TrackOutput* GetTrackFromReference(const TrackReference& ref);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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> ×, 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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`
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user