From 8cd96eae645a2cf16332c1f674bec16c0bfadf2e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 13 Apr 2019 02:40:58 +1000 Subject: [PATCH] nodes can now be connected through the node editor --- effects/effectrow.cpp | 57 +++++++++++++++++- effects/effectrow.h | 83 ++++++++++++++++++++++---- nodes/inputs/boolinput.cpp | 2 +- nodes/inputs/colorinput.cpp | 2 +- nodes/inputs/comboinput.cpp | 2 +- nodes/inputs/fileinput.cpp | 2 +- nodes/inputs/fontinput.cpp | 2 +- nodes/inputs/stringinput.cpp | 2 +- nodes/inputs/vecinput.cpp | 8 +-- nodes/node.cpp | 26 +++++++++ nodes/node.h | 9 ++- nodes/nodeedge.cpp | 21 +++++++ nodes/nodeedge.h | 39 +++++++++++++ nodes/nodeplug.cpp | 11 ---- nodes/nodeplug.h | 13 ----- nodes/nodes/nodemedia.cpp | 2 + olive.pro | 10 ++-- panels/nodeeditor.cpp | 49 +++++++++++++--- panels/nodeeditor.h | 5 ++ ui/nodeedgeui.cpp | 67 +++++++++++++++++++++ ui/nodeedgeui.h | 26 +++++++++ ui/nodeui.cpp | 109 ++++++++++++++++++++++++++++------- ui/nodeui.h | 16 ++++- ui/nodeview.cpp | 2 +- 24 files changed, 480 insertions(+), 85 deletions(-) create mode 100644 nodes/nodeedge.cpp create mode 100644 nodes/nodeedge.h delete mode 100644 nodes/nodeplug.cpp delete mode 100644 nodes/nodeplug.h create mode 100644 ui/nodeedgeui.cpp create mode 100644 ui/nodeedgeui.h diff --git a/effects/effectrow.cpp b/effects/effectrow.cpp index 7e2abaa7c..e60bea8b1 100644 --- a/effects/effectrow.cpp +++ b/effects/effectrow.cpp @@ -65,13 +65,54 @@ void EffectRow::AddField(EffectField *field) fields_.append(field); } -void EffectRow::AddNodeInput(olive::nodes::DataType type) +void EffectRow::AddAcceptedNodeInput(olive::nodes::DataType type) { Q_ASSERT(output_type_ == olive::nodes::kInvalid); accepted_inputs_.append(type); } +void EffectRow::ConnectEdge(EffectRow *output, EffectRow *input) +{ + Q_ASSERT(output->IsNodeOutput()); + Q_ASSERT(input->IsNodeInput()); + + if (!input->node_edges_.isEmpty()) { + DisconnectEdge(input->node_edges_.first()); + } + + NodeEdgePtr edge = std::make_shared(output, input); + + output->node_edges_.append(edge); + input->node_edges_.append(edge); + + emit output->EdgesChanged(); + emit input->EdgesChanged(); +} + +void EffectRow::DisconnectEdge(NodeEdgePtr edge) +{ + EffectRow* output = edge->output(); + EffectRow* input = edge->input(); + + output->node_edges_.removeAll(edge); + input->node_edges_.removeAll(edge); + + emit output->EdgesChanged(); + emit input->EdgesChanged(); +} + +QVector EffectRow::edges() +{ + QVector edges; + + for (int i=0;i edges(); + protected: /** * @brief Add a field to this row @@ -258,18 +317,6 @@ protected: */ void AddField(EffectField* Field); - /** - * @brief Adds a node data type that can be accepted by this input - * - * Allows this input to take a node connection from a data type specified by type. An input can take several data - * types. - * - * @param type - * - * The data type to add - */ - void AddNodeInput(olive::nodes::DataType type); - public slots: /** * @brief Go to previous keyframe @@ -332,6 +379,13 @@ signals: */ void Clicked(); + /** + * @brief Edges changed signal + * + * Signal emitted any time an edge is connected or disconnected from this row + */ + void EdgesChanged(); + private slots: /** * @brief Set keyframing enabled state @@ -402,6 +456,11 @@ private: * this. */ olive::nodes::DataType output_type_; + + /** + * @brief Internal array of node edges. Access with AddEdge() and RemoveEdge(). + */ + QVector node_edges_; }; #endif // EFFECTROW_H diff --git a/nodes/inputs/boolinput.cpp b/nodes/inputs/boolinput.cpp index ff58c005a..aa98181d6 100644 --- a/nodes/inputs/boolinput.cpp +++ b/nodes/inputs/boolinput.cpp @@ -7,7 +7,7 @@ BoolInput::BoolInput(Node* parent, const QString& id, const QString& name, bool connect(bool_field, SIGNAL(Toggled(bool)), this, SIGNAL(Toggled(bool))); AddField(bool_field); - AddNodeInput(olive::nodes::kBoolean); + AddAcceptedNodeInput(olive::nodes::kBoolean); } bool BoolInput::GetBoolAt(double timecode) diff --git a/nodes/inputs/colorinput.cpp b/nodes/inputs/colorinput.cpp index 6c12129d6..ade47dbd2 100644 --- a/nodes/inputs/colorinput.cpp +++ b/nodes/inputs/colorinput.cpp @@ -5,7 +5,7 @@ ColorInput::ColorInput(Node* parent, const QString& id, const QString& name, boo { AddField(new ColorField(this)); - AddNodeInput(olive::nodes::kColor); + AddAcceptedNodeInput(olive::nodes::kColor); } QColor ColorInput::GetColorAt(double timecode) diff --git a/nodes/inputs/comboinput.cpp b/nodes/inputs/comboinput.cpp index b257ea66e..395ff6ebf 100644 --- a/nodes/inputs/comboinput.cpp +++ b/nodes/inputs/comboinput.cpp @@ -7,7 +7,7 @@ ComboInput::ComboInput(Node* parent, const QString& id, const QString& name, boo connect(combo_field, SIGNAL(DataChanged(const QVariant&)), this, SIGNAL(DataChanged(const QVariant&))); AddField(combo_field); - AddNodeInput(olive::nodes::kCombo); + AddAcceptedNodeInput(olive::nodes::kCombo); } void ComboInput::AddItem(const QString &text, const QVariant &data) diff --git a/nodes/inputs/fileinput.cpp b/nodes/inputs/fileinput.cpp index 77d2406bf..4f8d5c808 100644 --- a/nodes/inputs/fileinput.cpp +++ b/nodes/inputs/fileinput.cpp @@ -5,7 +5,7 @@ FileInput::FileInput(Node* parent, const QString& id, const QString& name, bool { AddField(new FileField(this)); - AddNodeInput(olive::nodes::kFile); + AddAcceptedNodeInput(olive::nodes::kFile); } QString FileInput::GetFileAt(double timecode) diff --git a/nodes/inputs/fontinput.cpp b/nodes/inputs/fontinput.cpp index c5a901c7e..ec9ba7077 100644 --- a/nodes/inputs/fontinput.cpp +++ b/nodes/inputs/fontinput.cpp @@ -5,7 +5,7 @@ FontInput::FontInput(Node* parent, const QString& id, const QString& name, bool { AddField(new FontField(this)); - AddNodeInput(olive::nodes::kFont); + AddAcceptedNodeInput(olive::nodes::kFont); } QString FontInput::GetFontAt(double timecode) diff --git a/nodes/inputs/stringinput.cpp b/nodes/inputs/stringinput.cpp index 0cdfa6922..121051ea8 100644 --- a/nodes/inputs/stringinput.cpp +++ b/nodes/inputs/stringinput.cpp @@ -5,7 +5,7 @@ StringInput::StringInput(Node* parent, const QString& id, const QString& name, b { AddField(new StringField(this, rich_text)); - AddNodeInput(olive::nodes::kString); + AddAcceptedNodeInput(olive::nodes::kString); } QString StringInput::GetStringAt(double timecode) diff --git a/nodes/inputs/vecinput.cpp b/nodes/inputs/vecinput.cpp index 2626720f0..f99666c6b 100644 --- a/nodes/inputs/vecinput.cpp +++ b/nodes/inputs/vecinput.cpp @@ -15,15 +15,15 @@ VecInput::VecInput(Node* parent, const QString& id, const QString& name, int val AddField(new DoubleField(this)); } - AddNodeInput(olive::nodes::kFloat); + AddAcceptedNodeInput(olive::nodes::kFloat); if (values > 1) { - AddNodeInput(olive::nodes::kVec2); + AddAcceptedNodeInput(olive::nodes::kVec2); } if (values > 2) { - AddNodeInput(olive::nodes::kVec3); + AddAcceptedNodeInput(olive::nodes::kVec3); } if (values > 3) { - AddNodeInput(olive::nodes::kVec4); + AddAcceptedNodeInput(olive::nodes::kVec4); } } diff --git a/nodes/node.cpp b/nodes/node.cpp index efb3146e3..a2d6b7d9b 100644 --- a/nodes/node.cpp +++ b/nodes/node.cpp @@ -148,6 +148,11 @@ void Node::AddRow(EffectRow *row) rows.append(row); } +int Node::IndexOfRow(EffectRow *row) +{ + return rows.indexOf(row); +} + void Node::copy_field_keyframes(NodePtr e) { for (int i=0;i Node::GetAllEdges() +{ + QVector edges; + + for (int i=0;iedges()); + } + + return edges; +} + void Node::refresh() {} void Node::FieldChanged() { @@ -310,6 +326,11 @@ void Node::SetExpanded(bool e) expanded_ = e; } +void Node::SetPos(const QPointF &pos) +{ + pos_ = pos; +} + void Node::SetEnabled(bool b) { enabled_ = b; emit EnabledChanged(b); @@ -615,6 +636,11 @@ void Node::setIterations(int i) { iterations = i; } +const QPointF &Node::pos() +{ + return pos_; +} + void Node::process_image(double, uint8_t *, uint8_t *, int){} NodePtr Node::copy(Clip *c) { diff --git a/nodes/node.h b/nodes/node.h index c67a317af..b58fa1d78 100644 --- a/nodes/node.h +++ b/nodes/node.h @@ -127,7 +127,7 @@ public: virtual NodePtr Create(Clip *c) = 0; void AddRow(EffectRow* row); - + int IndexOfRow(EffectRow* row); EffectRow* row(int i); int row_count(); @@ -135,6 +135,8 @@ public: EffectGizmo* gizmo(int i); int gizmo_count(); + QVector GetAllEdges(); + bool IsEnabled(); bool IsExpanded(); @@ -168,6 +170,8 @@ public: int getIterations(); void setIterations(int i); + const QPointF& pos(); + virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); virtual void process_shader(double timecode, GLTextureCoords&, int iteration); virtual void process_coords(double timecode, GLTextureCoords& coords, int data); @@ -225,6 +229,7 @@ public slots: void FieldChanged(); void SetEnabled(bool b); void SetExpanded(bool e); + void SetPos(const QPointF& pos); signals: void EnabledChanged(bool); private slots: @@ -264,6 +269,8 @@ private: QVector gizmo_dragging_actions_; + QPointF pos_; + // superimpose functions virtual void redraw(double timecode); bool valueHasChanged(double timecode); diff --git a/nodes/nodeedge.cpp b/nodes/nodeedge.cpp new file mode 100644 index 000000000..da21eaac8 --- /dev/null +++ b/nodes/nodeedge.cpp @@ -0,0 +1,21 @@ +#include "nodeedge.h" + +#include + +#include "effects/effectrow.h" + +NodeEdge::NodeEdge(EffectRow *output, EffectRow *input) : + output_(output), + input_(input) +{ +} + +EffectRow *NodeEdge::output() +{ + return output_; +} + +EffectRow *NodeEdge::input() +{ + return input_; +} diff --git a/nodes/nodeedge.h b/nodes/nodeedge.h new file mode 100644 index 000000000..a6b49581d --- /dev/null +++ b/nodes/nodeedge.h @@ -0,0 +1,39 @@ +#ifndef NODEEDGE_H +#define NODEEDGE_H + +#include + +class EffectRow; + +class NodeEdge; +using NodeEdgePtr = std::shared_ptr; + +class NodeEdge +{ +public: + /** + * @brief NodeEdge Constructor + * + * Creates a node edge and stores its two connections. + * + * This should not be used directly. Use the static function EffectRow::ConnectEdge instead. + * + * @param output + * + * Output/from EffectRow that this edge "starts" at + * + * @param input + * + * Input/to EffectRow that this edge "ends" at + */ + NodeEdge(EffectRow* output, EffectRow* input); + + EffectRow* output(); + EffectRow* input(); + +private: + EffectRow* output_; + EffectRow* input_; +}; + +#endif // NODEEDGE_H diff --git a/nodes/nodeplug.cpp b/nodes/nodeplug.cpp deleted file mode 100644 index bb60f8397..000000000 --- a/nodes/nodeplug.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "nodeplug.h" - -NodePlug::NodePlug() -{ - -} - -bool NodePlug::IsConnected() -{ - -} diff --git a/nodes/nodeplug.h b/nodes/nodeplug.h deleted file mode 100644 index 764afc716..000000000 --- a/nodes/nodeplug.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NODEPLUG_H -#define NODEPLUG_H - - -class NodePlug -{ -public: - NodePlug(); - - bool IsConnected(); -}; - -#endif // NODEPLUG_H diff --git a/nodes/nodes/nodemedia.cpp b/nodes/nodes/nodemedia.cpp index 0035e900c..e835a884a 100644 --- a/nodes/nodes/nodemedia.cpp +++ b/nodes/nodes/nodemedia.cpp @@ -3,6 +3,8 @@ NodeMedia::NodeMedia(Clip* c) : Node(c) { + EffectRow* matrix_input = new EffectRow(this, "matrix", tr("Matrix"), true, false); + matrix_input->AddAcceptedNodeInput(olive::nodes::kMatrix); } QString NodeMedia::name() diff --git a/olive.pro b/olive.pro index 9d4b6542d..404cee082 100644 --- a/olive.pro +++ b/olive.pro @@ -191,7 +191,6 @@ SOURCES += \ ui/nodeui.cpp \ panels/effectspanel.cpp \ nodes/nodedatatypes.cpp \ - nodes/nodeplug.cpp \ nodes/inputs/boolinput.cpp \ nodes/inputs/comboinput.cpp \ nodes/inputs/colorinput.cpp \ @@ -207,7 +206,9 @@ SOURCES += \ nodes/nodes/nodeshader.cpp \ decoders/ffmpegdecoder.cpp \ decoders/decoder.cpp \ - nodes/node.cpp + nodes/node.cpp \ + nodes/nodeedge.cpp \ + ui/nodeedgeui.cpp HEADERS += \ ui/mainwindow.h \ @@ -353,7 +354,6 @@ HEADERS += \ ui/nodeui.h \ panels/effectspanel.h \ nodes/nodedatatypes.h \ - nodes/nodeplug.h \ nodes/inputs.h \ nodes/inputs/boolinput.h \ nodes/inputs/comboinput.h \ @@ -372,7 +372,9 @@ HEADERS += \ decoders/ffmpegdecoder.h \ decoders/decoder.h \ nodes/node.h \ - timeline/tracktypes.h + timeline/tracktypes.h \ + nodes/nodeedge.h \ + ui/nodeedgeui.h FORMS += diff --git a/panels/nodeeditor.cpp b/panels/nodeeditor.cpp index 73d24bd30..af7a1c89d 100644 --- a/panels/nodeeditor.cpp +++ b/panels/nodeeditor.cpp @@ -24,6 +24,8 @@ NodeEditor::NodeEditor(QWidget *parent) : view_.setInteractive(true); view_.setDragMode(QGraphicsView::RubberBandDrag); + + connect(&scene_, SIGNAL(changed(const QList&)), this, SLOT(ItemsChanged())); } void NodeEditor::Retranslate() @@ -32,9 +34,9 @@ void NodeEditor::Retranslate() void NodeEditor::LoadEvent() { - nodes_.resize(open_effects_.size()); - if (!open_effects_.isEmpty()) { + QVector added_edges; + Clip* first_clip = open_effects_.first()->GetEffect()->parent_clip; for (int i=0;iSetWidget(effect_ui); node_ui->AddToScene(&scene_); + node_ui->setPos(effect_ui->GetEffect()->pos()); - nodes_[i] = node_ui; + nodes_.append(node_ui); + + // Get node edges + QVector edges = open_effects_.at(i)->GetEffect()->GetAllEdges(); + for (int j=0;jadjust(); + } + + foreach (NodeUI* node, nodes_) { + node->Widget()->GetEffect()->SetPos(node->pos()); + } } diff --git a/panels/nodeeditor.h b/panels/nodeeditor.h index a404629c3..fd3ed0967 100644 --- a/panels/nodeeditor.h +++ b/panels/nodeeditor.h @@ -6,6 +6,7 @@ #include "effectspanel.h" #include "ui/nodeview.h" #include "ui/nodeui.h" +#include "ui/nodeedgeui.h" class NodeEditor : public EffectsPanel { Q_OBJECT @@ -22,6 +23,10 @@ private: QGraphicsScene scene_; NodeView view_; QVector nodes_; + QVector edges_; + +private slots: + void ItemsChanged(); }; diff --git a/ui/nodeedgeui.cpp b/ui/nodeedgeui.cpp new file mode 100644 index 000000000..61c0bde8c --- /dev/null +++ b/ui/nodeedgeui.cpp @@ -0,0 +1,67 @@ +#include "nodeedgeui.h" + +#include +#include + +#include "global/math.h" +#include "ui/effectui.h" + +NodeEdgeUI::NodeEdgeUI(NodeEdge* edge) : + edge_(edge), + output_node_(nullptr), + input_node_(nullptr) +{ + setPen(QPen(Qt::white, 2)); +} + +void NodeEdgeUI::adjust() +{ + if (output_node_ == nullptr) { + // Locate the output and input nodes' UIs + + QList all_items = scene()->items(); + + for (int j=0;j(all_items.at(j)); + if (node != nullptr) { + + // Check if this node has the output row + int row_index = node->Widget()->GetEffect()->IndexOfRow(edge_->output()); + + if (row_index > -1) { + output_node_ = node; + output_index_ = row_index; + } + + // Check if this node has the input row + row_index = node->Widget()->GetEffect()->IndexOfRow(edge_->input()); + + if (row_index > -1) { + input_node_ = node; + input_index_ = row_index; + } + } + } + } + + setPath(GetEdgePath(output_node_->pos() + output_node_->GetNodeSocketRects().at(output_index_).center(), + input_node_->pos() + input_node_->GetNodeSocketRects().at(input_index_).center())); +} + +NodeEdge *NodeEdgeUI::edge() +{ + return edge_; +} + +QPainterPath NodeEdgeUI::GetEdgePath(const QPointF &start_pos, const QPointF &end_pos) +{ + double mid_x = double_lerp(start_pos.x(), end_pos.x(), 0.5); + + QPainterPath path_; + path_.moveTo(start_pos); + path_.cubicTo(QPointF(mid_x, start_pos.y()), + QPointF(mid_x, end_pos.y()), + end_pos); + + return path_; +} diff --git a/ui/nodeedgeui.h b/ui/nodeedgeui.h new file mode 100644 index 000000000..3634334d2 --- /dev/null +++ b/ui/nodeedgeui.h @@ -0,0 +1,26 @@ +#ifndef NODEEDGEUI_H +#define NODEEDGEUI_H + +#include + +#include "nodeui.h" + +class NodeEdgeUI : public QGraphicsPathItem { +public: + NodeEdgeUI(NodeEdge* edge); + + static QPainterPath GetEdgePath(const QPointF& start_pos, const QPointF& end_pos); + + void adjust(); + NodeEdge* edge(); + +private: + NodeEdge* edge_; + + NodeUI* output_node_; + int output_index_; + NodeUI* input_node_; + int input_index_; +}; + +#endif // NODEEDGEUI_H diff --git a/ui/nodeui.cpp b/ui/nodeui.cpp index de263e07d..6b433bf84 100644 --- a/ui/nodeui.cpp +++ b/ui/nodeui.cpp @@ -12,13 +12,15 @@ #include #include "ui/effectui.h" -#include "global/math.h" +#include "ui/nodeedgeui.h" const int kRoundedRectRadius = 5; const int kNodePlugSize = 12; NodeUI::NodeUI() : central_widget_(nullptr), + proxy_(nullptr), + drag_destination_(nullptr), clicked_socket_(-1) { setFlag(QGraphicsItem::ItemIsMovable, true); @@ -29,7 +31,6 @@ NodeUI::~NodeUI() { if (scene() != nullptr) { scene()->removeItem(proxy_); - scene()->removeItem(this); } } @@ -55,8 +56,8 @@ void NodeUI::Resize(const QSize &s) rectangle.setWidth(rectangle.width() + kNodePlugSize); - path_ = QPainterPath(); - path_.addRoundedRect(inner_rect, kRoundedRectRadius, kRoundedRectRadius); + drag_path_ = QPainterPath(); + drag_path_.addRoundedRect(inner_rect, kRoundedRectRadius, kRoundedRectRadius); setRect(rectangle); } @@ -66,6 +67,11 @@ void NodeUI::SetWidget(EffectUI *widget) central_widget_ = widget; } +EffectUI *NodeUI::Widget() +{ + return central_widget_; +} + void NodeUI::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget) @@ -88,7 +94,7 @@ void NodeUI::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QW painter->setPen(palette.base().color()); } painter->setBrush(palette.window()); - painter->drawPath(path_); + painter->drawPath(drag_path_); } void NodeUI::mousePressEvent(QGraphicsSceneMouseEvent *event) @@ -96,6 +102,7 @@ void NodeUI::mousePressEvent(QGraphicsSceneMouseEvent *event) QVector sockets = GetNodeSocketRects(); clicked_socket_ = -1; + drag_destination_ = nullptr; for (int i=0;ipos())) { @@ -106,8 +113,7 @@ void NodeUI::mousePressEvent(QGraphicsSceneMouseEvent *event) if (clicked_socket_ > -1) { drag_line_start_ = pos() + sockets.at(clicked_socket_).center(); - drag_line_ = scene()->addPath(GetEdgePath(drag_line_start_, event->scenePos()), - QPen(Qt::white, 2)); + drag_line_ = scene()->addPath(NodeEdgeUI::GetEdgePath(drag_line_start_, event->scenePos())); event->accept(); } else { @@ -119,7 +125,65 @@ void NodeUI::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (clicked_socket_ > -1) { - drag_line_->setPath(GetEdgePath(drag_line_start_, event->scenePos())); + bool line_is_touching_node = false; + + QPointF drag_line_end = event->scenePos(); + + // Get all the graphics items at this mouse position + QList mouse_items = scene()->items(event->scenePos()); + for (int j=0;j(mouse_items.at(j)); + + if (mouse_node != nullptr) { + // If so, get this node's sockets and loop through them + QVector mouse_nodes_sockets = mouse_node->GetNodeSocketRects(); + for (int i=0;iscenePos() - mouse_node->pos())) { + + // If so, see if the two rows can be connected + + EffectRow* local_row = central_widget_->GetEffect()->row(clicked_socket_); + EffectRow* remote_row = mouse_node->GetRowFromIndex(i); + + // Ensure one is an input and one is an output and whether their data types are compatible + if (local_row->IsNodeInput() != remote_row->IsNodeInput()) { + + // Determine which row is the input and which row is the output + EffectRow* input_row = (local_row->IsNodeInput()) ? local_row : remote_row; + EffectRow* output_row = (local_row->IsNodeInput()) ? remote_row : local_row; + + if (input_row->CanAcceptDataType(output_row->OutputDataType())) { + // This is a valid connection + line_is_touching_node = true; + + // Snap drag line to this socket + drag_line_end = mouse_node->pos() + mouse_nodes_sockets.at(i).center(); + + // Cancel loop since we have a connection now + j = mouse_items.size(); + + // Cache destination row + drag_destination_ = remote_row; + } + } + + break; + } + } + } + } + + if (line_is_touching_node) { + drag_line_->setPen(QPen(Qt::white, 2)); + } else { + drag_line_->setPen(QPen(Qt::gray, 2)); + } + + drag_line_->setPath(NodeEdgeUI::GetEdgePath(drag_line_start_, drag_line_end)); event->accept(); @@ -132,26 +196,16 @@ void NodeUI::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (clicked_socket_ > -1) { scene()->removeItem(drag_line_); - delete drag_line_; event->accept(); + + if (drag_destination_ != nullptr) { + EffectRow::ConnectEdge(central_widget_->GetEffect()->row(clicked_socket_), drag_destination_); + } } else { QGraphicsItem::mouseReleaseEvent(event); } } -QPainterPath NodeUI::GetEdgePath(const QPointF &start_pos, const QPointF &end_pos) -{ - double mid_x = double_lerp(start_pos.x(), end_pos.x(), 0.5); - - QPainterPath path_; - path_.moveTo(start_pos); - path_.cubicTo(QPointF(mid_x, start_pos.y()), - QPointF(mid_x, end_pos.y()), - end_pos); - - return path_; -} - QVector NodeUI::GetNodeSocketRects() { QVector rects; @@ -176,3 +230,14 @@ QVector NodeUI::GetNodeSocketRects() return rects; } + +EffectRow *NodeUI::GetRowFromIndex(int i) +{ + if (central_widget_ != nullptr) { + Node* e = central_widget_->GetEffect(); + if (i < e->row_count()) { + return e->row(i); + } + } + return nullptr; +} diff --git a/ui/nodeui.h b/ui/nodeui.h index 2ac1b0c48..2b1f30696 100644 --- a/ui/nodeui.h +++ b/ui/nodeui.h @@ -5,6 +5,8 @@ #include class EffectUI; +class EffectRow; +class NodeEdge; class NodeUI : public QGraphicsRectItem { public: @@ -14,24 +16,32 @@ public: void AddToScene(QGraphicsScene* scene); void Resize(const QSize& s); void SetWidget(EffectUI* widget); + EffectUI* Widget(); + + QVector GetNodeSocketRects(); + protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; virtual void mousePressEvent(QGraphicsSceneMouseEvent * event) override; virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + private: - QVector GetNodeSocketRects(); - QPainterPath GetEdgePath(const QPointF& start_pos, const QPointF& end_pos); + EffectRow *GetRowFromIndex(int i); EffectUI* central_widget_; QGraphicsProxyWidget* proxy_; - QPainterPath path_; QGraphicsPathItem* drag_line_; QPointF drag_line_start_; + EffectRow* drag_destination_; + QPainterPath drag_path_; int clicked_socket_; + }; + + #endif // NODEUI_H diff --git a/ui/nodeview.cpp b/ui/nodeview.cpp index 3998fab9c..94366749d 100644 --- a/ui/nodeview.cpp +++ b/ui/nodeview.cpp @@ -42,9 +42,9 @@ void NodeView::mouseMoveEvent(QMouseEvent *event) void NodeView::mouseReleaseEvent(QMouseEvent *event) { if (!hand_moving_) { - hand_moving_ = false; QGraphicsView::mouseReleaseEvent(event); } + hand_moving_ = false; } void NodeView::wheelEvent(QWheelEvent *event)