reimplemented node positioning and deleting
This commit is contained in:
@@ -44,6 +44,19 @@ void NodeGraph::Clear()
|
||||
}
|
||||
}
|
||||
|
||||
int NodeGraph::GetNumberOfContextsNodeIsIn(Node *node, bool except_itself) const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
foreach (Node *ctx, node_children_) {
|
||||
if (ctx->ContextContainsNode(node) && (!except_itself || ctx != node)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void NodeGraph::childEvent(QChildEvent *event)
|
||||
{
|
||||
super::childEvent(event);
|
||||
|
||||
@@ -63,6 +63,8 @@ public:
|
||||
return default_nodes_;
|
||||
}
|
||||
|
||||
int GetNumberOfContextsNodeIsIn(Node *node, bool except_itself = false) const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted when a Node is added to the graph
|
||||
|
||||
@@ -210,7 +210,7 @@ bool LoadOTIOTask::Run()
|
||||
block->setParent(sequence->parent());
|
||||
|
||||
// Position transition in its own context
|
||||
sequence->parent()->SetNodePosition(block, block, QPointF(0, 0));
|
||||
block->SetNodePositionInContext(block, QPointF(0, 0));
|
||||
}
|
||||
|
||||
if (otio_block->schema_name() == "Gap") {
|
||||
@@ -218,7 +218,7 @@ bool LoadOTIOTask::Run()
|
||||
block->setParent(sequence->parent());
|
||||
|
||||
// Position transition in its own context
|
||||
sequence->parent()->SetNodePosition(block, block, QPointF(0, 0));
|
||||
block->SetNodePositionInContext(block, QPointF(0, 0));
|
||||
}
|
||||
|
||||
// Update this after it's used but before any continue statements
|
||||
@@ -246,7 +246,7 @@ bool LoadOTIOTask::Run()
|
||||
QFileInfo info(probed_item->filename());
|
||||
probed_item->SetLabel(info.fileName());
|
||||
|
||||
FolderAddChild add(sequence_footage, probed_item, true);
|
||||
FolderAddChild add(sequence_footage, probed_item);
|
||||
add.redo_now();
|
||||
}
|
||||
|
||||
@@ -254,10 +254,10 @@ bool LoadOTIOTask::Run()
|
||||
block->setParent(sequence->parent());
|
||||
|
||||
// Position clip in its own context
|
||||
sequence->parent()->SetNodePosition(block, block, QPointF(0, 0));
|
||||
block->SetNodePositionInContext(block, QPointF(0, 0));
|
||||
|
||||
// Position footage in its context
|
||||
sequence->parent()->SetNodePosition(probed_item, block, QPointF(-2, 0));
|
||||
block->SetNodePositionInContext(probed_item, QPointF(-2, 0));
|
||||
|
||||
|
||||
if (track->type() == Track::kVideo) {
|
||||
@@ -266,14 +266,14 @@ bool LoadOTIOTask::Run()
|
||||
|
||||
Node::ConnectEdge(probed_item, NodeInput(transform, TransformDistortNode::kTextureInput));
|
||||
Node::ConnectEdge(transform, NodeInput(block, ClipBlock::kBufferIn));
|
||||
sequence->parent()->SetNodePosition(transform, block, QPointF(-1, 0));
|
||||
block->SetNodePositionInContext(transform, QPointF(-1, 0));
|
||||
} else {
|
||||
VolumeNode* volume_node = new VolumeNode();
|
||||
volume_node->setParent(sequence->parent());
|
||||
|
||||
Node::ConnectEdge(probed_item, NodeInput(volume_node, VolumeNode::kSamplesInput));
|
||||
Node::ConnectEdge(volume_node, NodeInput(block, ClipBlock::kBufferIn));
|
||||
sequence->parent()->SetNodePosition(volume_node, block, QPointF(-1, 0));
|
||||
block->SetNodePositionInContext(volume_node, QPointF(-1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,43 +125,7 @@ void NodeView::ClearGraph()
|
||||
|
||||
void NodeView::DeleteSelected()
|
||||
{
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
{
|
||||
// First remove any selected edges
|
||||
QVector<NodeViewEdge *> selected_edges = scene_.GetSelectedEdges();
|
||||
|
||||
if (!selected_edges.isEmpty()) {
|
||||
Node::OutputConnections removed_connections(selected_edges.size());
|
||||
|
||||
for (int i=0; i<selected_edges.size(); i++) {
|
||||
NodeViewEdge* edge = selected_edges.at(i);
|
||||
command->add_child(new NodeEdgeRemoveCommand(edge->output(), edge->input()));
|
||||
removed_connections[i] = {edge->output(), edge->input()};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Secondly remove any nodes
|
||||
QVector<Node*> selected_nodes = scene_.GetSelectedNodes();
|
||||
|
||||
// Ensure no nodes are "undeletable"
|
||||
for (int i=0;i<selected_nodes.size();i++) {
|
||||
if (!selected_nodes.at(i)->CanBeDeleted()) {
|
||||
selected_nodes.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selected_nodes.isEmpty()) {
|
||||
for (Node* node : qAsConst(selected_nodes)) {
|
||||
command->add_child(new NodeRemoveAndDisconnectCommand(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
scene_.DeleteSelected();
|
||||
}
|
||||
|
||||
void NodeView::SelectAll()
|
||||
@@ -428,6 +392,11 @@ void NodeView::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
super::mousePressEvent(event);
|
||||
|
||||
auto selected_items = scene_.GetSelectedItems();
|
||||
foreach (NodeViewItem *i, selected_items) {
|
||||
dragging_nodes_.insert(i, i->GetNodePosition());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::mouseMoveEvent(QMouseEvent *event)
|
||||
@@ -658,6 +627,15 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
DetachItemsFromCursor();
|
||||
}
|
||||
|
||||
for (auto it=dragging_nodes_.cbegin(); it!=dragging_nodes_.cend(); it++) {
|
||||
NodeViewItem *i = it.key();
|
||||
QPointF current_pos = i->GetNodePosition();
|
||||
if (it.value() != current_pos) {
|
||||
command->add_child(new NodeSetPositionCommand(i->GetNode(), i->GetContext(), current_pos));
|
||||
}
|
||||
}
|
||||
dragging_nodes_.clear();
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
super::mouseReleaseEvent(event);
|
||||
|
||||
@@ -219,6 +219,8 @@ private:
|
||||
QVector<Node*> last_set_filter_nodes_;
|
||||
QMap<Node*, QPointF> context_offsets_;
|
||||
|
||||
QMap<NodeViewItem*, QPointF> dragging_nodes_;
|
||||
|
||||
double scale_;
|
||||
|
||||
bool create_edge_already_exists_;
|
||||
|
||||
@@ -50,9 +50,7 @@ void NodeViewContext::AddChild(Node *node)
|
||||
return;
|
||||
}
|
||||
|
||||
NodeViewItem *item = new NodeViewItem(this);
|
||||
item->SetNode(node, context_);
|
||||
item->SetNodePosition(context_->GetNodePositionInContext(node));
|
||||
NodeViewItem *item = new NodeViewItem(node, context_, this);
|
||||
item->SetFlowDirection(flow_dir_);
|
||||
|
||||
connect(node, &Node::InputConnected, this, &NodeViewContext::ChildInputConnected);
|
||||
@@ -162,6 +160,36 @@ void NodeViewContext::SetCurvedEdges(bool e)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::DeleteSelected(NodeViewDeleteCommand *command)
|
||||
{
|
||||
// Delete any selected edges
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
if (edge->isSelected()) {
|
||||
command->AddEdge(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any selected nodes
|
||||
foreach (NodeViewItem *node, item_map_) {
|
||||
if (node->isSelected()) {
|
||||
command->AddNode(node->GetNode(), context_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<NodeViewItem *> NodeViewContext::GetSelectedItems() const
|
||||
{
|
||||
QVector<NodeViewItem *> items;
|
||||
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
if (it.value()->isSelected()) {
|
||||
items.append(it.value());
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void NodeViewContext::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
// Set pen and brush
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "node/node.h"
|
||||
#include "nodeviewcommon.h"
|
||||
#include "nodeviewedge.h"
|
||||
#include "nodeviewundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -22,6 +23,10 @@ public:
|
||||
|
||||
void SetCurvedEdges(bool e);
|
||||
|
||||
void DeleteSelected(NodeViewDeleteCommand *command);
|
||||
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -39,10 +39,10 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeViewItem::NodeViewItem(QGraphicsItem *parent) :
|
||||
NodeViewItem::NodeViewItem(Node* n, Node *context, QGraphicsItem *parent) :
|
||||
QGraphicsRectItem(parent),
|
||||
node_(nullptr),
|
||||
context_(nullptr),
|
||||
node_(n),
|
||||
context_(context),
|
||||
expanded_(false),
|
||||
hide_titlebar_(false),
|
||||
highlighted_index_(-1),
|
||||
@@ -69,6 +69,24 @@ NodeViewItem::NodeViewItem(QGraphicsItem *parent) :
|
||||
setRect(title_bar_rect_);
|
||||
|
||||
output_connector_ = new NodeViewItemConnector(true, this);
|
||||
|
||||
// Set up node
|
||||
node_->Retranslate();
|
||||
|
||||
foreach (const QString& input, node_->inputs()) {
|
||||
if (node_->IsInputConnectable(input) && !node_->IsInputHidden(input)) {
|
||||
node_inputs_.append(input);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInputConnectors();
|
||||
|
||||
connect(node_, &Node::LabelChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
connect(node_, &Node::ColorChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
|
||||
SetNodePosition(context_->GetNodePositionInContext(node_));
|
||||
|
||||
SetExpanded(node_->property("expanded").toBool());
|
||||
}
|
||||
|
||||
QPointF NodeViewItem::GetNodePosition() const
|
||||
@@ -208,37 +226,6 @@ int NodeViewItem::GetIndexAt(QPointF pt) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
void NodeViewItem::SetNode(Node *n, Node *context)
|
||||
{
|
||||
if (node_) {
|
||||
disconnect(n, &Node::LabelChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
disconnect(n, &Node::ColorChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
}
|
||||
|
||||
node_ = n;
|
||||
context_ = context;
|
||||
|
||||
node_inputs_.clear();
|
||||
input_connectors_.clear();
|
||||
|
||||
if (node_) {
|
||||
node_->Retranslate();
|
||||
|
||||
foreach (const QString& input, node_->inputs()) {
|
||||
if (node_->IsInputConnectable(input) && !node_->IsInputHidden(input)) {
|
||||
node_inputs_.append(input);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInputConnectors();
|
||||
|
||||
connect(n, &Node::LabelChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
connect(n, &Node::ColorChanged, this, &NodeViewItem::NodeAppearanceChanged);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewItem::SetExpanded(bool e, bool hide_titlebar)
|
||||
{
|
||||
if (node_inputs_.isEmpty()
|
||||
@@ -248,6 +235,7 @@ void NodeViewItem::SetExpanded(bool e, bool hide_titlebar)
|
||||
|
||||
expanded_ = e;
|
||||
hide_titlebar_ = hide_titlebar;
|
||||
node_->setProperty("expanded", e);
|
||||
|
||||
if (expanded_ && !node_inputs_.isEmpty()) {
|
||||
// Create new rect
|
||||
@@ -507,8 +495,8 @@ void NodeViewItem::SetLabelAsOutput(bool e)
|
||||
|
||||
NodeViewEdge *NodeViewItem::GetEdgeFromInputConnector(NodeViewItemConnector *connector)
|
||||
{
|
||||
ssize_t index = -1;
|
||||
for (ssize_t i=0; i<ssize_t(input_connectors_.size()); i++) {
|
||||
int index = -1;
|
||||
for (int i=0; i<int(input_connectors_.size()); i++) {
|
||||
if (input_connectors_[i].get() == connector) {
|
||||
index = i;
|
||||
break;
|
||||
|
||||
@@ -45,16 +45,11 @@ class NodeViewItem : public QObject, public QGraphicsRectItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewItem(QGraphicsItem* parent = nullptr);
|
||||
NodeViewItem(Node* n, Node *context, QGraphicsItem* parent = nullptr);
|
||||
|
||||
QPointF GetNodePosition() const;
|
||||
void SetNodePosition(const QPointF& pos);
|
||||
|
||||
/**
|
||||
* @brief Set the Node to correspond to this widget
|
||||
*/
|
||||
void SetNode(Node* n, Node *context);
|
||||
|
||||
/**
|
||||
* @brief Get currently attached node
|
||||
*/
|
||||
@@ -63,6 +58,11 @@ public:
|
||||
return node_;
|
||||
}
|
||||
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get expanded state
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "nodeviewscene.h"
|
||||
|
||||
#include "common/functiontimer.h"
|
||||
#include "core.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
#include "nodeviewedge.h"
|
||||
#include "nodeviewitem.h"
|
||||
@@ -41,11 +42,6 @@ void NodeViewScene::SetFlowDirection(NodeViewCommon::FlowDirection direction)
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->SetFlowDirection(direction_);
|
||||
}
|
||||
|
||||
// Iterate over edge items setting direction
|
||||
foreach (NodeViewEdge* edge, edges_) {
|
||||
edge->SetFlowDirection(direction_);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewScene::clear()
|
||||
@@ -63,9 +59,6 @@ void NodeViewScene::clear()
|
||||
delete it.value();
|
||||
}
|
||||
item_map_.clear();
|
||||
|
||||
qDeleteAll(edges_);
|
||||
edges_.clear();
|
||||
}
|
||||
|
||||
void NodeViewScene::SelectAll()
|
||||
@@ -86,22 +79,22 @@ void NodeViewScene::DeselectAll()
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewScene::DeleteSelected()
|
||||
{
|
||||
NodeViewDeleteCommand* command = new NodeViewDeleteCommand();
|
||||
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
ctx->DeleteSelected(command);
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
NodeViewItem *NodeViewScene::NodeToUIObject(Node *n)
|
||||
{
|
||||
return item_map_.value(n);
|
||||
}
|
||||
|
||||
NodeViewEdge *NodeViewScene::EdgeToUIObject(Node *output, const NodeInput& input)
|
||||
{
|
||||
foreach (NodeViewEdge* edge, edges_) {
|
||||
if (edge->output() == output && edge->input() == input) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVector<Node *> NodeViewScene::GetSelectedNodes() const
|
||||
{
|
||||
QHash<Node*, NodeViewItem*>::const_iterator iterator;
|
||||
@@ -118,29 +111,13 @@ QVector<Node *> NodeViewScene::GetSelectedNodes() const
|
||||
|
||||
QVector<NodeViewItem *> NodeViewScene::GetSelectedItems() const
|
||||
{
|
||||
QHash<Node*, NodeViewItem*>::const_iterator iterator;
|
||||
QVector<NodeViewItem *> selected;
|
||||
QVector<NodeViewItem *> items;
|
||||
|
||||
for (iterator=item_map_.begin();iterator!=item_map_.end();iterator++) {
|
||||
if (iterator.value()->isSelected()) {
|
||||
selected.append(iterator.value());
|
||||
}
|
||||
foreach (NodeViewContext *ctx, context_map_) {
|
||||
items.append(ctx->GetSelectedItems());
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
QVector<NodeViewEdge *> NodeViewScene::GetSelectedEdges() const
|
||||
{
|
||||
QVector<NodeViewEdge*> edges;
|
||||
|
||||
foreach (NodeViewEdge* e, edges_) {
|
||||
if (e->isSelected()) {
|
||||
edges.append(e);
|
||||
}
|
||||
}
|
||||
|
||||
return edges;
|
||||
return items;
|
||||
}
|
||||
|
||||
NodeViewContext *NodeViewScene::AddContext(Node *node)
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void DeleteSelected();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the graphical widget corresponding to a specific Node
|
||||
*
|
||||
@@ -54,22 +56,15 @@ public:
|
||||
* in this view/scene), this function returns nullptr.
|
||||
*/
|
||||
NodeViewItem* NodeToUIObject(Node* n);
|
||||
NodeViewEdge *EdgeToUIObject(Node *output, const NodeInput &input);
|
||||
|
||||
QVector<Node *> GetSelectedNodes() const;
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
QVector<NodeViewEdge*> GetSelectedEdges() const;
|
||||
|
||||
const QHash<Node*, NodeViewItem*>& item_map() const
|
||||
{
|
||||
return item_map_;
|
||||
}
|
||||
|
||||
const QVector<NodeViewEdge*>& edges() const
|
||||
{
|
||||
return edges_;
|
||||
}
|
||||
|
||||
Qt::Orientation GetFlowOrientation() const;
|
||||
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const;
|
||||
@@ -96,8 +91,6 @@ private:
|
||||
|
||||
QHash<Node*, NodeViewItem*> item_map_;
|
||||
|
||||
QVector<NodeViewEdge*> edges_;
|
||||
|
||||
NodeGraph* graph_;
|
||||
|
||||
NodeViewCommon::FlowDirection direction_;
|
||||
|
||||
@@ -193,4 +193,100 @@ void NodeOverrideColorCommand::undo()
|
||||
node_->SetOverrideColor(old_index_);
|
||||
}
|
||||
|
||||
NodeViewDeleteCommand::NodeViewDeleteCommand()
|
||||
{
|
||||
}
|
||||
|
||||
void NodeViewDeleteCommand::AddNode(Node *node, Node *context)
|
||||
{
|
||||
foreach (const NodePair &pair, nodes_) {
|
||||
if (pair.first == node && pair.second == context) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nodes_.append(NodePair({node, context}));
|
||||
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (context->ContextContainsNode(it->second)) {
|
||||
AddEdge(it->second, it->first);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
|
||||
if (context->ContextContainsNode(it->second.node())) {
|
||||
AddEdge(it->first, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewDeleteCommand::AddEdge(Node *output, const NodeInput &input)
|
||||
{
|
||||
foreach (const Node::OutputConnection &edge, edges_) {
|
||||
if (edge.first == output && edge.second == input) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
edges_.append({output, input});
|
||||
}
|
||||
|
||||
Project *NodeViewDeleteCommand::GetRelevantProject() const
|
||||
{
|
||||
if (!nodes_.isEmpty()) {
|
||||
return nodes_.first().first->project();
|
||||
}
|
||||
|
||||
if (!edges_.isEmpty()) {
|
||||
return edges_.first().first->project();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeViewDeleteCommand::redo()
|
||||
{
|
||||
foreach (const Node::OutputConnection &edge, edges_) {
|
||||
Node::DisconnectEdge(edge.first, edge.second);
|
||||
}
|
||||
|
||||
foreach (const NodePair &pair, nodes_) {
|
||||
RemovedNode rn;
|
||||
|
||||
rn.node = pair.first;
|
||||
rn.context = pair.second;
|
||||
rn.pos = rn.context->GetNodePositionInContext(rn.node);
|
||||
|
||||
rn.context->RemoveNodeFromContext(rn.node);
|
||||
|
||||
// If node is no longer in any contexts and is not connected to anything, remove it
|
||||
if (rn.node->parent()->GetNumberOfContextsNodeIsIn(rn.node, true) == 0
|
||||
&& rn.node->input_connections().empty()
|
||||
&& rn.node->output_connections().empty()) {
|
||||
rn.removed_from_graph = rn.node->parent();
|
||||
rn.node->setParent(&memory_manager_);
|
||||
} else {
|
||||
rn.removed_from_graph = nullptr;
|
||||
}
|
||||
|
||||
removed_nodes_.append(rn);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewDeleteCommand::undo()
|
||||
{
|
||||
for (auto rn=removed_nodes_.crbegin(); rn!=removed_nodes_.crend(); rn++) {
|
||||
if (rn->removed_from_graph) {
|
||||
rn->node->setParent(rn->removed_from_graph);
|
||||
}
|
||||
|
||||
rn->context->SetNodePositionInContext(rn->node, rn->pos);
|
||||
}
|
||||
removed_nodes_.clear();
|
||||
|
||||
for (auto edge=edges_.crbegin(); edge!=edges_.crend(); edge++) {
|
||||
Node::ConnectEdge(edge->first, edge->second);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -363,6 +363,42 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeViewDeleteCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
NodeViewDeleteCommand();
|
||||
|
||||
void AddNode(Node *node, Node *context);
|
||||
|
||||
void AddEdge(Node *output, const NodeInput &input);
|
||||
|
||||
virtual Project * GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
using NodePair = QPair<Node *, Node*>;
|
||||
|
||||
QVector<NodePair> nodes_;
|
||||
|
||||
QVector<Node::OutputConnection> edges_;
|
||||
|
||||
struct RemovedNode {
|
||||
Node *node;
|
||||
Node *context;
|
||||
QPointF pos;
|
||||
NodeGraph *removed_from_graph;
|
||||
};
|
||||
|
||||
QVector<RemovedNode> removed_nodes_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEVIEWUNDO_H
|
||||
|
||||
Reference in New Issue
Block a user