use strings to connect nodes
This makes the node system somewhat more high-level with the intent of making working with them far more flexible and stable. By making the architecture more abstracted, it becomes far less rigid which should allow us to do even more with it and make it much less crash prone.
This commit is contained in:
@@ -40,7 +40,6 @@ NodeView::NodeView(QWidget *parent) :
|
||||
drop_edge_(nullptr),
|
||||
create_edge_(nullptr),
|
||||
create_edge_dst_(nullptr),
|
||||
create_edge_dst_input_(nullptr),
|
||||
create_edge_dst_temp_expanded_(false),
|
||||
filter_mode_(kFilterShowSelectedBlocks),
|
||||
scale_(1.0)
|
||||
@@ -103,10 +102,8 @@ void NodeView::SetGraph(NodeGraph *graph)
|
||||
}
|
||||
|
||||
foreach (Node* n, graph_->nodes()) {
|
||||
foreach (NodeInput* input, n->parameters()) {
|
||||
for (auto it=input->edges().cbegin(); it!=input->edges().cend(); it++) {
|
||||
scene_.AddEdge(it->second, input, it->first);
|
||||
}
|
||||
for (auto it=n->input_connections().cbegin(); it!=n->input_connections().cend(); it++) {
|
||||
scene_.AddEdge(it->second, it->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +121,7 @@ void NodeView::DeleteSelected()
|
||||
QVector<NodeViewEdge *> selected_edges = scene_.GetSelectedEdges();
|
||||
|
||||
foreach (NodeViewEdge* edge, selected_edges) {
|
||||
command->add_child(new NodeEdgeRemoveCommand(edge->output(), edge->input(), edge->element()));
|
||||
command->add_child(new NodeEdgeRemoveCommand(edge->output(), edge->input()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,18 +423,18 @@ void NodeView::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
if (highlight_index >= 0) {
|
||||
create_edge_dst_input_ = create_edge_dst_->GetInputAtIndex(highlight_index);
|
||||
create_edge_->SetPoints(create_edge_src_->GetOutputPoint(),
|
||||
create_edge_dst_->GetInputPoint(highlight_index, create_edge_src_->pos()),
|
||||
create_edge_->SetPoints(create_edge_src_->GetOutputPoint(Node::kDefaultOutput),
|
||||
create_edge_dst_->GetInputPoint(create_edge_dst_input_.input(), create_edge_dst_input_.element(), create_edge_src_->pos()),
|
||||
true);
|
||||
} else {
|
||||
create_edge_dst_input_ = nullptr;
|
||||
create_edge_->SetPoints(create_edge_src_->GetOutputPoint(),
|
||||
create_edge_dst_input_.Reset();
|
||||
create_edge_->SetPoints(create_edge_src_->GetOutputPoint(Node::kDefaultOutput),
|
||||
scene_pt,
|
||||
false);
|
||||
}
|
||||
|
||||
// Set connected to whether we have a valid input destination
|
||||
create_edge_->SetConnected(create_edge_dst_input_);
|
||||
create_edge_->SetConnected(create_edge_dst_input_.IsValid());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -466,20 +463,22 @@ void NodeView::mouseMoveEvent(QMouseEvent *event)
|
||||
new_drop_edge = dynamic_cast<NodeViewEdge*>(item);
|
||||
|
||||
if (new_drop_edge) {
|
||||
drop_input_ = nullptr;
|
||||
drop_input_.Reset();
|
||||
|
||||
foreach (NodeInput* input, attached_node->parameters()) {
|
||||
if (input->IsConnectable()) {
|
||||
if (input->GetDataType() == new_drop_edge->input()->GetDataType()) {
|
||||
drop_input_ = input;
|
||||
foreach (const QString& input, attached_node->inputs()) {
|
||||
NodeInput i(attached_node, input);
|
||||
|
||||
if (attached_node->IsInputConnectable(input)) {
|
||||
if (attached_node->GetInputDataType(input) == new_drop_edge->input().GetDataType()) {
|
||||
drop_input_ = i;
|
||||
break;
|
||||
} else if (!drop_input_) {
|
||||
drop_input_ = input;
|
||||
} else if (!drop_input_.IsValid()) {
|
||||
drop_input_ = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_input_) {
|
||||
if (drop_input_.IsValid()) {
|
||||
break;
|
||||
} else {
|
||||
new_drop_edge = nullptr;
|
||||
@@ -519,10 +518,10 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
create_edge_dst_->SetExpanded(false);
|
||||
}
|
||||
|
||||
if (create_edge_dst_input_) {
|
||||
if (create_edge_dst_input_.IsValid()) {
|
||||
// Make connection
|
||||
Core::instance()->undo_stack()->push(new NodeEdgeAddCommand(create_edge_src_->GetNode(), create_edge_dst_input_, -1));
|
||||
create_edge_dst_input_ = nullptr;
|
||||
Core::instance()->undo_stack()->push(new NodeEdgeAddCommand(create_edge_src_->GetNode(), create_edge_dst_input_));
|
||||
create_edge_dst_input_.Reset();
|
||||
}
|
||||
|
||||
create_edge_dst_ = nullptr;
|
||||
@@ -539,11 +538,11 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
// Remove old edge
|
||||
command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input(), drop_edge_->element()));
|
||||
command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input()));
|
||||
|
||||
// Place new edges
|
||||
command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_, -1));
|
||||
command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input(), drop_edge_->element()));
|
||||
command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_));
|
||||
command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input()));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
@@ -107,12 +107,12 @@ private:
|
||||
QList<AttachedItem> attached_items_;
|
||||
|
||||
NodeViewEdge* drop_edge_;
|
||||
NodeInput* drop_input_;
|
||||
NodeInput drop_input_;
|
||||
|
||||
NodeViewEdge* create_edge_;
|
||||
NodeViewItem* create_edge_src_;
|
||||
NodeViewItem* create_edge_dst_;
|
||||
NodeInput* create_edge_dst_input_;
|
||||
NodeInput create_edge_dst_input_;
|
||||
bool create_edge_dst_temp_expanded_;
|
||||
|
||||
NodeViewScene scene_;
|
||||
|
||||
@@ -33,13 +33,12 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeViewEdge::NodeViewEdge(Node* output, NodeInput *input, int element,
|
||||
NodeViewEdge::NodeViewEdge(const NodeOutput &output, const NodeInput &input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent) :
|
||||
QGraphicsPathItem(parent),
|
||||
output_(output),
|
||||
input_(input),
|
||||
element_(element),
|
||||
from_item_(from_item),
|
||||
to_item_(to_item)
|
||||
{
|
||||
@@ -56,8 +55,8 @@ NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
|
||||
void NodeViewEdge::Adjust()
|
||||
{
|
||||
// Draw a line between the two
|
||||
SetPoints(from_item()->GetOutputPoint(),
|
||||
to_item()->GetInputPoint(input_, from_item()->pos()),
|
||||
SetPoints(from_item()->GetOutputPoint(output_.output()),
|
||||
to_item()->GetInputPoint(input_.input(), input_.element(), from_item()->pos()),
|
||||
to_item()->IsExpanded());
|
||||
}
|
||||
|
||||
|
||||
@@ -39,18 +39,18 @@ class NodeViewItem;
|
||||
class NodeViewEdge : public QGraphicsPathItem
|
||||
{
|
||||
public:
|
||||
NodeViewEdge(Node* output, NodeInput *input, int element,
|
||||
NodeViewEdge(const NodeOutput& output, const NodeInput& input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent = nullptr);
|
||||
|
||||
NodeViewEdge(QGraphicsItem* parent = nullptr);
|
||||
|
||||
Node* output() const
|
||||
const NodeOutput& output() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
|
||||
NodeInput* input() const
|
||||
const NodeInput& input() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
@@ -112,9 +112,9 @@ protected:
|
||||
private:
|
||||
void Init();
|
||||
|
||||
Node* output_;
|
||||
NodeOutput output_;
|
||||
|
||||
NodeInput* input_;
|
||||
NodeInput input_;
|
||||
|
||||
int element_;
|
||||
|
||||
|
||||
@@ -187,8 +187,8 @@ void NodeViewItem::SetNode(Node *n)
|
||||
if (node_) {
|
||||
node_->Retranslate();
|
||||
|
||||
foreach (NodeInput* input, node_->parameters()) {
|
||||
if (input->IsConnectable()) {
|
||||
foreach (const QString& input, node_->inputs()) {
|
||||
if (node_->IsInputConnectable(input)) {
|
||||
node_inputs_.append(input);
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
painter->fillRect(input_rect, highlight_col);
|
||||
}
|
||||
|
||||
painter->drawText(input_rect, Qt::AlignCenter, node_inputs_.at(i)->name());
|
||||
painter->drawText(input_rect, Qt::AlignCenter, node_->GetInputName(node_inputs_.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,17 +430,12 @@ QRectF NodeViewItem::GetInputRect(int index) const
|
||||
return r;
|
||||
}
|
||||
|
||||
QPointF NodeViewItem::GetInputPoint(NodeInput *input, const QPointF& source_pos) const
|
||||
QPointF NodeViewItem::GetInputPoint(const QString &input, int element, const QPointF& source_pos) const
|
||||
{
|
||||
return GetInputPoint(node_inputs_.indexOf(input), source_pos);
|
||||
return pos() + GetInputPointInternal(node_inputs_.indexOf(input), source_pos);
|
||||
}
|
||||
|
||||
QPointF NodeViewItem::GetInputPoint(int input, const QPointF &source_pos) const
|
||||
{
|
||||
return pos() + GetInputPointInternal(input, source_pos);
|
||||
}
|
||||
|
||||
QPointF NodeViewItem::GetOutputPoint() const
|
||||
QPointF NodeViewItem::GetOutputPoint(const QString& output) const
|
||||
{
|
||||
switch (flow_dir_) {
|
||||
case NodeViewCommon::kLeftToRight:
|
||||
|
||||
@@ -78,10 +78,9 @@ public:
|
||||
/**
|
||||
* @brief Returns GLOBAL point that edges should connect to for any NodeParam member of this object
|
||||
*/
|
||||
QPointF GetInputPoint(NodeInput* input, const QPointF &source_pos) const;
|
||||
QPointF GetInputPoint(int input, const QPointF &source_pos) const;
|
||||
QPointF GetInputPoint(const QString& input, int element, const QPointF &source_pos) const;
|
||||
|
||||
QPointF GetOutputPoint() const;
|
||||
QPointF GetOutputPoint(const QString &output) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the direction nodes are flowing
|
||||
@@ -105,9 +104,9 @@ public:
|
||||
|
||||
int GetIndexAt(QPointF pt) const;
|
||||
|
||||
NodeInput* GetInputAtIndex(int index) const
|
||||
NodeInput GetInputAtIndex(int index) const
|
||||
{
|
||||
return node_inputs_.at(index);
|
||||
return NodeInput(node_, node_inputs_.at(index));
|
||||
}
|
||||
|
||||
void SetHighlightedIndex(int index);
|
||||
@@ -143,7 +142,7 @@ private:
|
||||
/**
|
||||
* @brief Cached list of node inputs
|
||||
*/
|
||||
QList<NodeInput*> node_inputs_;
|
||||
QVector<QString> node_inputs_;
|
||||
|
||||
/**
|
||||
* @brief Rectangle of the Node's title bar (equal to rect() when collapsed)
|
||||
|
||||
@@ -98,10 +98,10 @@ NodeViewItem *NodeViewScene::NodeToUIObject(Node *n)
|
||||
return item_map_.value(n);
|
||||
}
|
||||
|
||||
NodeViewEdge *NodeViewScene::EdgeToUIObject(Node* output, NodeInput* input, int element)
|
||||
NodeViewEdge *NodeViewScene::EdgeToUIObject(const NodeOutput& output, const NodeInput& input)
|
||||
{
|
||||
foreach (NodeViewEdge* edge, edges_) {
|
||||
if (edge->output() == output && edge->input() == input && edge->element() == element) {
|
||||
if (edge->output() == output && edge->input() == input) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
@@ -174,14 +174,14 @@ void NodeViewScene::RemoveNode(Node *node)
|
||||
delete item_map_.take(node);
|
||||
}
|
||||
|
||||
void NodeViewScene::AddEdge(Node* output, NodeInput* input, int element)
|
||||
void NodeViewScene::AddEdge(const NodeOutput &output, const NodeInput &input)
|
||||
{
|
||||
AddEdgeInternal(output, input, element, NodeToUIObject(output), NodeToUIObject(input->parent()));
|
||||
AddEdgeInternal(output, input, NodeToUIObject(output.node()), NodeToUIObject(input.node()));
|
||||
}
|
||||
|
||||
void NodeViewScene::RemoveEdge(Node* output, NodeInput* input, int element)
|
||||
void NodeViewScene::RemoveEdge(const NodeOutput &output, const NodeInput &input)
|
||||
{
|
||||
NodeViewEdge* edge = EdgeToUIObject(output, input, element);
|
||||
NodeViewEdge* edge = EdgeToUIObject(output, input);
|
||||
edge->from_item()->RemoveEdge(edge);
|
||||
edge->to_item()->RemoveEdge(edge);
|
||||
edges_.removeOne(edge);
|
||||
@@ -203,9 +203,9 @@ int NodeViewScene::DetermineWeight(Node *n)
|
||||
return qMax(1, weight);
|
||||
}
|
||||
|
||||
void NodeViewScene::AddEdgeInternal(Node *output, NodeInput *input, int element, NodeViewItem *from, NodeViewItem *to)
|
||||
void NodeViewScene::AddEdgeInternal(const NodeOutput& output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to)
|
||||
{
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge(output, input, element, from, to);
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge(output, input, from, to);
|
||||
|
||||
edge_ui->SetFlowDirection(direction_);
|
||||
edge_ui->SetCurved(curved_edges_);
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
* in this view/scene), this function returns nullptr.
|
||||
*/
|
||||
NodeViewItem* NodeToUIObject(Node* n);
|
||||
NodeViewEdge *EdgeToUIObject(Node* output, NodeInput *input, int element);
|
||||
NodeViewEdge *EdgeToUIObject(const NodeOutput &output, const NodeInput &input);
|
||||
|
||||
QVector<Node *> GetSelectedNodes() const;
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
@@ -98,8 +98,8 @@ public slots:
|
||||
*/
|
||||
void RemoveNode(Node* node);
|
||||
|
||||
void AddEdge(Node* output, NodeInput* input, int element);
|
||||
void RemoveEdge(Node* output, NodeInput* input, int element);
|
||||
void AddEdge(const NodeOutput& output, const NodeInput& input);
|
||||
void RemoveEdge(const NodeOutput& output, const NodeInput& input);
|
||||
|
||||
/**
|
||||
* @brief Set whether edges in this scene should be curved or not
|
||||
@@ -109,7 +109,7 @@ public slots:
|
||||
private:
|
||||
static int DetermineWeight(Node* n);
|
||||
|
||||
void AddEdgeInternal(Node* output, NodeInput* input, int element, NodeViewItem* from, NodeViewItem* to);
|
||||
void AddEdgeInternal(const NodeOutput &output, const NodeInput &input, NodeViewItem* from, NodeViewItem* to);
|
||||
|
||||
QHash<Node*, NodeViewItem*> item_map_;
|
||||
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, NodeInput *input, int element) :
|
||||
NodeEdgeAddCommand::NodeEdgeAddCommand(const NodeOutput &output, const NodeInput &input) :
|
||||
output_(output),
|
||||
input_(input),
|
||||
element_(element),
|
||||
remove_command_(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -40,22 +39,20 @@ NodeEdgeAddCommand::~NodeEdgeAddCommand()
|
||||
|
||||
void NodeEdgeAddCommand::redo()
|
||||
{
|
||||
if (input_->IsConnected(element_)) {
|
||||
if (input_.IsConnected()) {
|
||||
if (!remove_command_) {
|
||||
remove_command_ = new NodeEdgeRemoveCommand(input_->GetConnectedNode(element_),
|
||||
input_,
|
||||
element_);
|
||||
remove_command_ = new NodeEdgeRemoveCommand(input_.GetConnectedOutput(), input_);
|
||||
}
|
||||
|
||||
remove_command_->redo();
|
||||
}
|
||||
|
||||
Node::ConnectEdge(output_, input_, element_);
|
||||
Node::ConnectEdge(output_, input_);
|
||||
}
|
||||
|
||||
void NodeEdgeAddCommand::undo()
|
||||
{
|
||||
Node::DisconnectEdge(output_, input_, element_);
|
||||
Node::DisconnectEdge(output_, input_);
|
||||
|
||||
if (remove_command_) {
|
||||
remove_command_->undo();
|
||||
@@ -64,29 +61,28 @@ void NodeEdgeAddCommand::undo()
|
||||
|
||||
Project *NodeEdgeAddCommand::GetRelevantProject() const
|
||||
{
|
||||
return output_->parent()->project();
|
||||
return output_.node()->parent()->project();
|
||||
}
|
||||
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, NodeInput *input, int element) :
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(const NodeOutput &output, const NodeInput &input) :
|
||||
output_(output),
|
||||
input_(input),
|
||||
element_(element)
|
||||
input_(input)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeEdgeRemoveCommand::redo()
|
||||
{
|
||||
Node::DisconnectEdge(output_, input_, element_);
|
||||
Node::DisconnectEdge(output_, input_);
|
||||
}
|
||||
|
||||
void NodeEdgeRemoveCommand::undo()
|
||||
{
|
||||
Node::ConnectEdge(output_, input_, element_);
|
||||
Node::ConnectEdge(output_, input_);
|
||||
}
|
||||
|
||||
Project *NodeEdgeRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return output_->parent()->project();
|
||||
return output_.node()->parent()->project();
|
||||
}
|
||||
|
||||
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node) :
|
||||
@@ -134,14 +130,12 @@ void NodeRemoveAndDisconnectCommand::prep()
|
||||
}
|
||||
|
||||
// Disconnect everything
|
||||
foreach (const Node::InputConnection& conn, node_->edges()) {
|
||||
command_->add_child(new NodeEdgeRemoveCommand(node_, conn.input, conn.element));
|
||||
for (auto it=node_->input_connections().cbegin(); it!=node_->input_connections().cend(); it++) {
|
||||
command_->add_child(new NodeEdgeRemoveCommand(it->second, it->first));
|
||||
}
|
||||
|
||||
foreach (NodeInput* input, node_->inputs()) {
|
||||
for (auto it=input->edges().cbegin(); it!=input->edges().cend(); it++) {
|
||||
command_->add_child(new NodeEdgeRemoveCommand(it->second, input, it->first));
|
||||
}
|
||||
for (const Node::OutputConnection& conn : node_->output_connections()) {
|
||||
command_->add_child(new NodeEdgeRemoveCommand(conn.first, conn.second));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace olive {
|
||||
*/
|
||||
class NodeEdgeRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
NodeEdgeRemoveCommand(Node* output, NodeInput* input, int element);
|
||||
NodeEdgeRemoveCommand(const NodeOutput& output, const NodeInput& input);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
@@ -42,9 +42,8 @@ public:
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Node* output_;
|
||||
NodeInput* input_;
|
||||
int element_;
|
||||
NodeOutput output_;
|
||||
NodeInput input_;
|
||||
|
||||
};
|
||||
|
||||
@@ -55,7 +54,7 @@ private:
|
||||
*/
|
||||
class NodeEdgeAddCommand : public UndoCommand {
|
||||
public:
|
||||
NodeEdgeAddCommand(Node* output, NodeInput* input, int element);
|
||||
NodeEdgeAddCommand(const NodeOutput& output, const NodeInput& input);
|
||||
|
||||
virtual ~NodeEdgeAddCommand() override;
|
||||
|
||||
@@ -65,9 +64,8 @@ public:
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Node* output_;
|
||||
NodeInput* input_;
|
||||
int element_;
|
||||
NodeOutput output_;
|
||||
NodeInput input_;
|
||||
|
||||
NodeEdgeRemoveCommand* remove_command_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user