diff --git a/app/node/node.h b/app/node/node.h index bc546f908..5f9c8134a 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -1395,6 +1395,37 @@ private: }; +class NodeSetPositionToOffsetOfAnotherNodeCommand : public UndoCommand +{ +public: + NodeSetPositionToOffsetOfAnotherNodeCommand(Node* node, Node* other_node, const QPointF& offset) : + node_(node), + other_node_(other_node), + offset_(offset) + {} + + virtual Project * GetRelevantProject() const override + { + return node_->project(); + } + + virtual void redo() override + { + node_->SetPosition(other_node_->GetPosition() + offset_); + } + + virtual void undo() override + { + node_->SetPosition(other_node_->GetPosition() - offset_); + } + +private: + Node* node_; + Node* other_node_; + QPointF offset_; + +}; + } #endif // NODE_H diff --git a/app/widget/timelinewidget/timelineundo.h b/app/widget/timelinewidget/timelineundo.h index 6ff13abdc..9264278a8 100644 --- a/app/widget/timelinewidget/timelineundo.h +++ b/app/widget/timelinewidget/timelineundo.h @@ -1469,6 +1469,7 @@ public: { delete ripple_remove_command_; qDeleteAll(add_track_commands_); + qDeleteAll(position_commands_); } virtual Project* GetRelevantProject() const override @@ -1511,20 +1512,41 @@ public: } track->AppendBlock(insert_); + + if (position_commands_.isEmpty()) { + // Create position commands for insert and gap if necessary + if (gap_) { + position_commands_.append(new NodeSetPositionAsChildCommand(gap_, track, gap_->index(), track->Blocks().size(), true)); + } + position_commands_.append(new NodeSetPositionAsChildCommand(insert_, track, insert_->index(), track->Blocks().size(), true)); + } } else { // Place the Block at this point if (!ripple_remove_command_) { ripple_remove_command_ = new TrackRippleRemoveAreaCommand(track, TimeRange(in_, in_ + insert_->length())); + } ripple_remove_command_->redo(); track->InsertBlockAfter(insert_, ripple_remove_command_->GetInsertionIndex()); + + if (position_commands_.isEmpty()) { + position_commands_.append(new NodeSetPositionAsChildCommand(insert_, track, insert_->index(), track->Blocks().size(), true)); + } + } + + for (int i=0; iredo(); } } virtual void undo() override { + for (int i=position_commands_.size()-1; i>=0; i--) { + position_commands_.at(i)->undo(); + } + Track* t = timeline_->GetTrackAt(track_index_); // Firstly, remove our insert @@ -1553,6 +1575,7 @@ private: QVector add_track_commands_; QObject memory_manager_; TrackRippleRemoveAreaCommand* ripple_remove_command_; + QVector position_commands_; }; diff --git a/app/widget/timelinewidget/tool/import.cpp b/app/widget/timelinewidget/tool/import.cpp index 8343b531e..d5d89725e 100644 --- a/app/widget/timelinewidget/tool/import.cpp +++ b/app/widget/timelinewidget/tool/import.cpp @@ -429,6 +429,7 @@ void ImportTool::DropGhosts(bool insert) clip->set_length_and_media_out(ghost->GetLength()); clip->SetLabel(footage_stream.footage->GetLabel()); command->add_child(new NodeAddCommand(dst_graph, clip)); + command->add_child(new NodeSetPositionToOffsetOfAnotherNodeCommand(clip, footage_stream.footage, QPointF(2, 0))); switch (footage_stream.footage->GetTypeFromOutput(footage_stream.output)) { case Stream::kVideo: @@ -438,6 +439,7 @@ void ImportTool::DropGhosts(bool insert) command->add_child(new NodeEdgeAddCommand(corresponding_output, NodeInput(transform, TransformDistortNode::kTextureInput))); command->add_child(new NodeEdgeAddCommand(transform, NodeInput(clip, ClipBlock::kBufferIn))); + command->add_child(new NodeSetPositionToOffsetOfAnotherNodeCommand(transform, clip, QPointF(-1, 0))); break; } case Stream::kAudio: @@ -447,6 +449,7 @@ void ImportTool::DropGhosts(bool insert) command->add_child(new NodeEdgeAddCommand(corresponding_output, NodeInput(volume_node, VolumeNode::kSamplesInput))); command->add_child(new NodeEdgeAddCommand(volume_node, NodeInput(clip, ClipBlock::kBufferIn))); + command->add_child(new NodeSetPositionToOffsetOfAnotherNodeCommand(volume_node, clip, QPointF(-1, 0))); break; } default: