timeline: allow pasting nodes into or over clips
This commit is contained in:
@@ -29,7 +29,6 @@
|
||||
#include "common/functiontimer.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "node/project/serializer/serializer.h"
|
||||
#include "widget/nodeparamview/nodeparamviewundo.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
@@ -611,26 +610,24 @@ bool NodeParamView::Paste()
|
||||
}
|
||||
}
|
||||
|
||||
return Paste(this, std::bind(&NodeParamView::GenerateExistingPasteMap, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
bool NodeParamView::Paste(QWidget *parent, std::function<QHash<Node *, Node*>(const ProjectSerializer::Result &)> get_existing_map_function)
|
||||
{
|
||||
ProjectSerializer::Result res = ProjectSerializer::Paste(QStringLiteral("nodes"));
|
||||
if (res.GetLoadedNodes().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine if any nodes of this type are already in the editor
|
||||
QVector<Node*> ignore_nodes;
|
||||
QMap<Node*, Node*> existing_nodes;
|
||||
for (Node *n : res.GetLoadedNodes()) {
|
||||
if (Node *existing = GetNodeWithIDAndIgnoreList(n->id(), ignore_nodes)) {
|
||||
existing_nodes.insert(existing, n);
|
||||
ignore_nodes.append(existing);
|
||||
}
|
||||
}
|
||||
QHash<Node*, Node*> existing_nodes = get_existing_map_function(res);
|
||||
|
||||
QVector<Node*> nodes_to_paste_as_new = res.GetLoadedNodes();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
if (!existing_nodes.empty()) {
|
||||
QMessageBox b(this);
|
||||
QMessageBox b(parent);
|
||||
b.setWindowTitle(tr("Paste Nodes"));
|
||||
|
||||
QStringList node_names;
|
||||
@@ -870,6 +867,19 @@ void NodeParamView::ToggleSelect(NodeParamViewItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
QHash<Node *, Node *> NodeParamView::GenerateExistingPasteMap(const ProjectSerializer::Result &r)
|
||||
{
|
||||
QVector<Node*> ignore_nodes;
|
||||
QHash<Node*, Node*> existing_nodes;
|
||||
for (Node *n : r.GetLoadedNodes()) {
|
||||
if (Node *existing = GetNodeWithIDAndIgnoreList(n->id(), ignore_nodes)) {
|
||||
existing_nodes.insert(existing, n);
|
||||
ignore_nodes.append(existing);
|
||||
}
|
||||
}
|
||||
return existing_nodes;
|
||||
}
|
||||
|
||||
void NodeParamView::UpdateGlobalScrollBar()
|
||||
{
|
||||
if (keyframe_view_) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "node/project/serializer/serializer.h"
|
||||
#include "nodeparamviewcontext.h"
|
||||
#include "nodeparamviewdockarea.h"
|
||||
#include "nodeparamviewitem.h"
|
||||
@@ -75,6 +76,7 @@ public:
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
|
||||
virtual bool Paste() override;
|
||||
static bool Paste(QWidget *parent, std::function<QHash<Node *, Node*>(const ProjectSerializer::Result &)> get_existing_map_function);
|
||||
|
||||
public slots:
|
||||
void SetContexts(const QVector<Node*> &contexts);
|
||||
@@ -134,6 +136,8 @@ private:
|
||||
|
||||
void ToggleSelect(NodeParamViewItem *item);
|
||||
|
||||
QHash<Node *, Node *> GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
|
||||
KeyframeView* keyframe_view_;
|
||||
|
||||
QVector<NodeParamViewContext*> context_items_;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "undo/timelineundoworkarea.h"
|
||||
#include "widget/menu/menu.h"
|
||||
#include "widget/menu/menushared.h"
|
||||
#include "widget/nodeparamview/nodeparamview.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
@@ -640,13 +641,23 @@ bool TimelineWidget::CopySelected(bool cut)
|
||||
|
||||
bool TimelineWidget::Paste()
|
||||
{
|
||||
// TimeRuler gets first chance (markers, etc.)
|
||||
if (super::Paste()) {
|
||||
return true;
|
||||
} if (!GetConnectedNode()) {
|
||||
}
|
||||
|
||||
// Ensure we have a connected node
|
||||
if (!GetConnectedNode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PasteInternal(false);
|
||||
// Attempt regular clip pasting
|
||||
if (PasteInternal(false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Give last chance to NodeParamView
|
||||
return NodeParamView::Paste(this, std::bind(&TimelineWidget::GenerateExistingPasteMap, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void TimelineWidget::PasteInsert()
|
||||
@@ -1707,6 +1718,24 @@ TimelineAndTrackView *TimelineWidget::AddTimelineAndTrackView(Qt::Alignment alig
|
||||
return v;
|
||||
}
|
||||
|
||||
QHash<Node *, Node *> TimelineWidget::GenerateExistingPasteMap(const ProjectSerializer::Result &r)
|
||||
{
|
||||
QHash<Node *, Node *> m;
|
||||
|
||||
for (Node *n : r.GetLoadedNodes()) {
|
||||
for (Block *b : qAsConst(this->selected_blocks_)) {
|
||||
for (auto it=b->GetContextPositions().cbegin(); it!=b->GetContextPositions().cend(); it++) {
|
||||
if (it.key()->id() == n->id() && !m.contains(it.key())) {
|
||||
m.insert(it.key(), n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
QByteArray TimelineWidget::SaveSplitterState() const
|
||||
{
|
||||
return view_splitter_->saveState();
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "core.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "node/project/serializer/serializer.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timelineandtrackview.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
@@ -311,6 +312,8 @@ private:
|
||||
|
||||
TimelineAndTrackView *AddTimelineAndTrackView(Qt::Alignment alignment);
|
||||
|
||||
QHash<Node*, Node*> GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
|
||||
QPoint drag_origin_;
|
||||
|
||||
QRubberBand rubberband_;
|
||||
|
||||
Reference in New Issue
Block a user