nodes can now be connected through the node editor

This commit is contained in:
itsmattkc
2019-04-13 02:40:58 +10:00
parent 6b67727bd8
commit 8cd96eae64
24 changed files with 480 additions and 85 deletions
+67
View File
@@ -0,0 +1,67 @@
#include "nodeedgeui.h"
#include <QPen>
#include <QGraphicsScene>
#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<QGraphicsItem*> all_items = scene()->items();
for (int j=0;j<all_items.size();j++) {
NodeUI* node = dynamic_cast<NodeUI*>(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_;
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef NODEEDGEUI_H
#define NODEEDGEUI_H
#include <QGraphicsPathItem>
#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
+87 -22
View File
@@ -12,13 +12,15 @@
#include <QPainter>
#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<QRectF> sockets = GetNodeSocketRects();
clicked_socket_ = -1;
drag_destination_ = nullptr;
for (int i=0;i<sockets.size();i++) {
if (sockets.at(i).contains(event->pos())) {
@@ -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<QGraphicsItem *> mouse_items = scene()->items(event->scenePos());
for (int j=0;j<mouse_items.size();j++) {
// See if the graphics item here is a node
NodeUI* mouse_node = dynamic_cast<NodeUI*>(mouse_items.at(j));
if (mouse_node != nullptr) {
// If so, get this node's sockets and loop through them
QVector<QRectF> mouse_nodes_sockets = mouse_node->GetNodeSocketRects();
for (int i=0;i<mouse_nodes_sockets.size();i++) {
// See if this socket contains the mouse cursor
if (mouse_nodes_sockets.at(i).contains(event->scenePos() - 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<QRectF> NodeUI::GetNodeSocketRects()
{
QVector<QRectF> rects;
@@ -176,3 +230,14 @@ QVector<QRectF> 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;
}
+13 -3
View File
@@ -5,6 +5,8 @@
#include <QGraphicsItem>
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<QRectF> 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<QRectF> 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
+1 -1
View File
@@ -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)