nodes can now be connected through the node editor
This commit is contained in:
+87
-22
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user