refactor: fix file case

This commit is contained in:
2025-07-10 13:49:25 +01:00
parent 9350b64567
commit 2d0c8fcfba
34 changed files with 72 additions and 72 deletions

View File

@@ -0,0 +1,73 @@
#include "Gui/Network/DisplayFlagButton.h"
#include "Gui/Network/NodeGraphic.h"
#include <QPainter>
#include <qgraphicsitem.h>
#include <qnamespace.h>
DisplayFlagButton::DisplayFlagButton(QGraphicsItem *parent)
: QGraphicsItem(parent)
{
constexpr float width = 8;
const float height = static_cast<NodeGraphic*>(parent)->getBodyRect().height()*0.8;
baseRect_ = QRectF(-width/2.0f, -height/2.0f, width, height);
setAcceptHoverEvents(true);
disabledBrush_ = QBrush(disabledColor_);
enabledBrush_ = QBrush(enabledColor_);
hoveredEnabledBrush_ = QBrush("#1391ff");
hoveredDisabledBrush_ = QBrush(hoveredColor_);
}
void DisplayFlagButton::setEnabled(bool enabled)
{
enabled_ = enabled;
update();
}
void DisplayFlagButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::NoPen);
// painter->setBrush(QBrush(disabledColor_));
QBrush usedBrush;
if(enabled_)
{
if(hovered_) { usedBrush = hoveredEnabledBrush_; }
else { usedBrush = enabledBrush_; }
}
else
{
if(hovered_) { usedBrush = hoveredDisabledBrush_; }
else { usedBrush = disabledBrush_; }
}
painter->setBrush(usedBrush);
constexpr float roundRad = 3;
painter->drawRoundedRect(baseRect_, roundRad, roundRad);
}
QRectF DisplayFlagButton::boundingRect() const
{
return baseRect_;
}
float DisplayFlagButton::getWidth()
{
return baseRect_.width();
}
void DisplayFlagButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
hovered_ = true;
update();
}
void DisplayFlagButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
hovered_ = false;
update();
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <QGraphicsItem>
#include <QBrush>
class DisplayFlagButton
: public QGraphicsItem
{
public:
DisplayFlagButton(QGraphicsItem *parent = nullptr);
float getWidth();
void setEnabled(bool enabled);
private:
QRectF baseRect_;
QColor disabledColor_=QColor("#373737");
QColor enabledColor_=QColor("#00BFFF");
QColor hoveredColor_=QColor("#666666");
QBrush disabledBrush_;
QBrush enabledBrush_;
QBrush hoveredDisabledBrush_;
QBrush hoveredEnabledBrush_;
bool hovered_=false;
bool enabled_=false;
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
};

View File

@@ -0,0 +1,53 @@
#include "Gui/Network/FloatingEdgeGraphic.h"
#include <QTextDocument>
#include "Gui/Network/SocketGraphic.h"
#include <iostream>
#include <qgraphicsitem.h>
#include <algorithm>
FloatingEdgeGraphic::FloatingEdgeGraphic(SocketGraphic* socket1, QGraphicsItem *parent)
: QGraphicsItem(parent), socket1_{socket1}
{
floatPos_ = socket1_->scenePos();
setZValue(-1);
}
QRectF FloatingEdgeGraphic::boundingRect() const
{
auto boundRect = QRectF(socket1_->scenePos(), floatPos_).normalized();
return boundRect;
}
void FloatingEdgeGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// auto pen = QPen("white");
QLinearGradient gradient(socket1_->scenePos(), floatPos_);
gradient.setColorAt(0.0, QColor(255, 255, 255, 255));
gradient.setColorAt(1.0, QColor(255, 255, 255, 50));
QPen pen(QBrush(gradient), 1);
pen.setCapStyle(Qt::RoundCap);
painter->setPen(pen);
// painter->drawLine(socket1_->scenePos(),floatPos_);
QPointF pos1 = socket1_->getIO()==enzo::nt::SocketIOType::Input ? socket1_->scenePos() : floatPos_;
QPointF pos2 = socket1_->getIO()==enzo::nt::SocketIOType::Input ? floatPos_ : socket1_->scenePos();
float dist = std::sqrt(std::pow(pos1.x()-pos2.x(),2)+std::pow(pos1.y()-pos2.y(),2));
float cubicStrength = dist*0.5;
cubicStrength = std::clamp(cubicStrength, 0.0f, 40.0f);
QPainterPath path;
path.moveTo(pos1);
path.cubicTo(pos1-QPoint(0,cubicStrength), pos2+QPoint(0,cubicStrength), pos2);
painter->drawPath(path);
}
void FloatingEdgeGraphic::setFloatPos(QPointF floatPos) {
prepareGeometryChange();
floatPos_ = floatPos;
update();
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <QGraphicsItem>
#include "Gui/Network/SocketGraphic.h"
#include <QPainter>
class FloatingEdgeGraphic
: public QGraphicsItem
{
public:
FloatingEdgeGraphic(SocketGraphic* socket1, QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void setFloatPos(QPointF floatPos);
private:
SocketGraphic* socket1_;
QPointF floatPos_;
};

392
src/Gui/Network/Network.cpp Normal file
View File

@@ -0,0 +1,392 @@
#include "Gui/Network/Network.h"
#include "Engine/Operator/GeometryConnection.h"
#include "Engine/Operator/GeometryOperator.h"
#include "Engine/Types.h"
#include "Gui/Network/DisplayFlagButton.h"
#include "Gui/Network/NodeEdgeGraphic.h"
#include "Gui/Network/NetworkGraphicsView.h"
#include "Gui/Network/NetworkGraphicsScene.h"
#include "Gui/Network/NodeGraphic.h"
#include "Gui/Network/FloatingEdgeGraphic.h"
#include "Gui/Network/SocketGraphic.h"
#include "Engine/Network/NetworkManager.h"
#include <memory>
#include <qboxlayout.h>
#include <QPushButton>
#include <QGraphicsItem>
#include <QMouseEvent>
#include <qgraphicsitem.h>
#include <qnamespace.h>
#include <QLine>
using namespace enzo;
Network::Network(QWidget* parent)
: QWidget(parent)
{
mainLayout_ = new QVBoxLayout(parent);
// mainLayout_->setContentsMargins(0,0,0,0);
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setLayout(mainLayout_);
scene_ = new NetworkGraphicsScene();
view_ = new NetworkGraphicsView(this, this, scene_);
mainLayout_->addWidget(view_);
}
void Network::resizeEvent(QResizeEvent *event)
{
QPainterPath path;
constexpr float radius = 10;
path.addRoundedRect(mainLayout_->contentsRect(), radius, radius);
QRegion region = QRegion(path.toFillPolygon().toPolygon());
this->setMask(region);
}
void Network::deleteEdge(QGraphicsItem* edge)
{
std::cout << "----\ndeleting edge\n";
if(!edge) return;
if(prevHoverItem_==edge)
{
prevHoverItem_=nullptr;
}
// scene_->removeItem(edge);
// scene_->update();
// view_->update();
// NOTE: deleting edge kept giving me segmentation faults
// I coundn't figure it out so I'm just leaving it for now
// delete edge;
static_cast<NodeEdgeGraphic*>(edge)->cleanUp();
std::cout << "finished deleting edge\n----\n";
}
void Network::mousePressEvent(QMouseEvent *event)
{
if( event->buttons() & Qt::LeftButton)
{
leftMousePressed(event);
}
}
void Network::leftMousePressed(QMouseEvent *event)
{
std::cout << "LEFT MOUSE PRESSED\n";
Qt::KeyboardModifiers mods = event->modifiers();
leftMouseStart = event->pos();
// QGraphicsItem* itemClicked = view_->itemAt(event->pos());
QList<QGraphicsItem*> clickedItems = view_->items(event->pos());
QGraphicsItem* clickedSocket = itemOfType<SocketGraphic>(clickedItems);
QGraphicsItem* clickedEdge = itemOfType<NodeEdgeGraphic>(clickedItems);
// delete edges
if(mods & Qt::ControlModifier && clickedEdge)
{
deleteEdge(clickedEdge);
}
// socket logic
else if(clickedSocket)
{
// find closest socket
clickedSocket = closestItemOfType<SocketGraphic>(clickedItems, view_->mapToScene(event->pos()));
if(clickedSocket)
{
socketClicked(static_cast<SocketGraphic*>(clickedSocket), event);
}
}
// floating edge
else if(floatingEdge_)
{
destroyFloatingEdge();
}
else if(QGraphicsItem* clickedNode = itemOfType<NodeGraphic>(clickedItems))
{
nodeMoveDelta_=clickedNode->pos()-view_->mapToScene(event->pos());
std::cout << "move delta: " << nodeMoveDelta_.x() << " " << nodeMoveDelta_.y() << "\n";
state_=State::MOVING_NODE;
moveNodeBuffer.clear();
moveNodeBuffer.push_back(clickedNode);
}
}
void Network::socketClicked(SocketGraphic* socket, QMouseEvent *event)
{
std::cout << "socket clicked\n";
// if first click
if(!floatingEdge_)
{
startSocket_=socket;
std::cout << "creating floating edge\n";
floatingEdge_ = new FloatingEdgeGraphic(socket);
scene_->addItem(floatingEdge_);
floatingEdge_->setFloatPos(view_->mapToScene(event->pos()));
}
// second click
// connect to opposite type
else if (
socket->getIO()!=startSocket_->getIO() &&
startSocket_->getOpId()!=socket->getOpId()
)
{
// order sockets in relation to data flow
// the input node is the node the data flows from
auto inputNodeSocket = socket->getIO()==enzo::nt::SocketIOType::Output ? socket : startSocket_;
// the output node is the node the data flows to
auto outputNodeSocket = startSocket_->getIO()==enzo::nt::SocketIOType::Input ? startSocket_ : socket;
std::cout << "CONNECTING opid: " << inputNodeSocket->getOpId() << " -> " << outputNodeSocket->getOpId() << "\n";
nt::connectOperators(inputNodeSocket->getOpId(), inputNodeSocket->getIndex(), outputNodeSocket->getOpId(), outputNodeSocket->getIndex());
NodeEdgeGraphic* newEdge = new NodeEdgeGraphic(outputNodeSocket, inputNodeSocket);
newEdge->setPos(outputNodeSocket->scenePos(), inputNodeSocket->scenePos());
scene_->addItem(newEdge);
destroyFloatingEdge();
}
}
void Network::destroyFloatingEdge()
{
if(floatingEdge_)
{
scene_->removeItem(floatingEdge_);
delete floatingEdge_;
floatingEdge_=nullptr;
}
}
void Network::mouseMoved(QMouseEvent *event)
{
// cache and reset prev hover item
QGraphicsItem* prevHoverItem=prevHoverItem_;
prevHoverItem_=nullptr;
// modifiers
Qt::KeyboardModifiers mods = event->modifiers();
bool ctrlMod = mods & Qt::ControlModifier;
QList<QGraphicsItem*> hoverItems = view_->items(event->pos());
if(state_==State::MOVING_NODE)
{
moveNodes(view_->mapToScene(event->pos())+nodeMoveDelta_);
return;
}
if(floatingEdge_)
{
if(
SocketGraphic* hoverSocket = static_cast<SocketGraphic*>(closestItemOfType<SocketGraphic>(hoverItems, view_->mapToScene(event->pos())));
hoverSocket &&
hoverSocket!=startSocket_ &&
hoverSocket->getIO()!=startSocket_->getIO() &&
hoverSocket->getOpId()!=startSocket_->getOpId()
)
{
floatingEdge_->setFloatPos(hoverSocket->scenePos());
}
else
{
floatingEdge_->setFloatPos(view_->mapToScene(event->pos()));
}
event->accept();
return;
}
QGraphicsItem* hoverEdge = itemOfType<NodeEdgeGraphic>(hoverItems);
// set node edge color
if(ctrlMod && hoverEdge)
{
if(event->buttons() & Qt::LeftButton)
{
deleteEdge(hoverEdge);
}
else
{
std::cout << "highlighting\n";
highlightEdge(hoverEdge, true);
}
}
// reset node edge color
if(
prevHoverItem &&
(!ctrlMod || hoverEdge!=prevHoverItem)
)
{
std::cout << "unhighlighting\n";
highlightEdge(prevHoverItem, false);
}
}
void Network::moveNodes(QPointF pos)
{
for(auto node : moveNodeBuffer)
{
node->setPos(pos);
}
}
void Network::keyPressEvent(QKeyEvent *event)
{
// modifiers
Qt::KeyboardModifiers mods = event->modifiers();
bool ctrlMod = mods & Qt::ControlModifier;
// get pos
QPoint globalPos = QCursor::pos();
QPoint widgetPos = mapFromGlobal(globalPos);
QPointF viewPos = view_->mapToScene(widgetPos);
QList<QGraphicsItem*> hoverItems = view_->items(widgetPos);
// edge detection
switch(event->key())
{
case( Qt::Key_Control):
{
QGraphicsItem* hoverItem = itemOfType<NodeEdgeGraphic>(hoverItems);
if(hoverItem!=nullptr)
{
highlightEdge(hoverItem, true);
}
break;
}
case(Qt::Key_Escape):
{
destroyFloatingEdge();
break;
}
case(Qt::Key_Tab):
{
if(auto newNode = createNode())
{
newNode->setPos(viewPos);
}
break;
}
}
}
NodeGraphic* Network::createNode()
{
if(nt::OpId id = nt::NetworkManager::addOperator())
{
NodeGraphic* newNode = new NodeGraphic(id);
scene_->addItem(newNode);
nodeStore_.emplace(id, newNode);
return newNode;
}
else
{
return nullptr;
}
}
void Network::highlightEdge(QGraphicsItem* edge, bool state)
{
if(!edge || !isType<NodeEdgeGraphic>(edge)) return;
if(state)
{
static_cast<NodeEdgeGraphic*>(edge)->setDeleteHighlight(true);
prevHoverItem_=edge;
// NOTE: sloppy fix for color not updating
view_->update();
}
else
{
static_cast<NodeEdgeGraphic*>(edge)->setDeleteHighlight(false);
// NOTE: sloppy fix for color not updating
view_->update();
}
}
void Network::keyReleaseEvent(QKeyEvent *event)
{
// modifiers
Qt::KeyboardModifiers mods = event->modifiers();
bool ctrlMod = mods & Qt::ControlModifier;
// edge detection
if(
prevHoverItem_ &&
event->key() == Qt::Key_Control &&
isType<NodeEdgeGraphic>(prevHoverItem_)
)
{
highlightEdge(prevHoverItem_, false);
}
}
void Network::mouseReleaseEvent(QMouseEvent *event)
{
// std::cout << "----\nMOUSE RELEASED\n---\n";
QList<QGraphicsItem*> hoverItems = view_->items(event->pos());
QGraphicsItem* hoverSocket = itemOfType<SocketGraphic>(hoverItems);
if(event->button() == Qt::LeftButton)
{
// display flag
if(
QGraphicsItem* clickedDisplayFlag = itemOfType<DisplayFlagButton>(hoverItems);
clickedDisplayFlag &&
QLineF(event->pos(), leftMouseStart).length()<5.0f
)
{
enzo::nt::NetworkManager* nm = enzo::nt::NetworkManager::getInstance();
NodeGraphic* clickedNode = static_cast<NodeGraphic*>(itemOfType<NodeGraphic>(hoverItems));
enzo::nt::OpId opId = clickedNode->getOpId();
if(auto prevDisplayOpId = nt::NetworkManager::getDisplayOp(); prevDisplayOpId)
{
NodeGraphic* prevDisplayNode = nodeStore_.at(*prevDisplayOpId);
prevDisplayNode->setDisplayFlag(false);
}
nm->setDisplayOp(opId);
static_cast<DisplayFlagButton*>(clickedDisplayFlag)->setEnabled(true);
}
if(state_==State::MOVING_NODE)
{
moveNodeBuffer.clear();
state_=State::DEFAULT;
}
else if(floatingEdge_ && hoverSocket)
{
hoverSocket = closestItemOfType<SocketGraphic>(hoverItems, view_->mapToScene(event->pos()));
if(hoverSocket)
{
socketClicked(static_cast<SocketGraphic*>(hoverSocket), event);
}
}
}
}

121
src/Gui/Network/Network.h Normal file
View File

@@ -0,0 +1,121 @@
#pragma once
#include <QWidget>
#include <iterator>
#include <memory>
#include <qgraphicsitem.h>
#include <qpoint.h>
#include <typeinfo>
#include "Engine/Network/NetworkManager.h"
#include "Engine/Types.h"
#include "Gui/Network/NetworkGraphicsView.h"
#include "Gui/Network/NodeEdgeGraphic.h"
#include "Gui/Network/NetworkGraphicsScene.h"
#include "Gui/Network/NodeGraphic.h"
#include "Gui/Network/SocketGraphic.h"
#include "Gui/Network/FloatingEdgeGraphic.h"
#include <iostream>
#include <QPointer>
#include <unordered_map>
class Network
: public QWidget
{
public:
Network(QWidget* parent = nullptr);
void socketClicked(SocketGraphic* socket, QMouseEvent *event);
void mouseMoved(QMouseEvent *event);
QSize sizeHint() const override { return QSize(-1, -1); }
enum class State
{
DEFAULT,
MOVING_NODE
};
private:
QLayout* mainLayout_;
NetworkGraphicsScene* scene_;
NetworkGraphicsView* view_;
std::unordered_map<enzo::nt::OpId, NodeGraphic*> nodeStore_;
FloatingEdgeGraphic* floatingEdge_=nullptr;
SocketGraphic* startSocket_=nullptr;
QGraphicsItem* prevHoverItem_=nullptr;
// nodes currently being moved
std::vector<QGraphicsItem*> moveNodeBuffer;
QPointF nodeMoveDelta_;
State state_=State::DEFAULT;
QPointF leftMouseStart;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void destroyFloatingEdge();
void deleteEdge(QGraphicsItem* edge);
NodeGraphic* createNode();
void highlightEdge(QGraphicsItem* edge, bool state);
void leftMousePressed(QMouseEvent* event);
void moveNodes(QPointF pos);
template<typename T>
bool isType(QGraphicsItem* item)
{
return item && typeid(*item)==typeid(T);
}
template<typename T>
QGraphicsItem* itemOfType(QList<QGraphicsItem*> items)
{
for(QGraphicsItem* item : items)
{
if(item && typeid(*item)==typeid(T))
{
return item;
}
}
return nullptr;
}
template<typename T>
QGraphicsItem* closestItemOfType(QList<QGraphicsItem*> items, QPointF centerPos)
{
std::vector <QGraphicsItem*> filteredItems;
for(QGraphicsItem* item : items)
{
if(item && typeid(*item)==typeid(T))
{
filteredItems.push_back(item);
}
}
if(filteredItems.size()==0) return nullptr;
if(filteredItems.size()==1) return filteredItems.at(0);
QGraphicsItem* closestItem=filteredItems.at(0);
float closestDist=QLineF(closestItem->scenePos(), centerPos).length();
for(size_t i=1; i<filteredItems.size(); ++i)
{
QGraphicsItem* item = filteredItems.at(i);
auto currentDist = QLineF(item->scenePos(), centerPos).length();
if(currentDist < closestDist)
{
closestItem = item;
closestDist = currentDist;
}
}
return closestItem;
}
protected:
void resizeEvent(QResizeEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
};

View File

@@ -0,0 +1,54 @@
#include "Gui/Network/NetworkGraphicsScene.h"
#include <QGraphicsScene>
#include <QGraphicsSceneWheelEvent>
#include <iostream>
#include <qgraphicsview.h>
#include <QPainterPath>
NetworkGraphicsScene::NetworkGraphicsScene()
: QGraphicsScene()
{
sceneWidth_ = 64000;
sceneHeight_ = 64000;
gridSize_ = 40;
setSceneRect(sceneWidth_/-2.0f, sceneHeight_/-2.0f, sceneWidth_, sceneHeight_);
setBackgroundBrush(QColor("#282828"));
}
void NetworkGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
{
// QPainterPath path;
// path.addRoundedRect(rect, 15, 15);
// painter->setClipPath(path);
QGraphicsScene::drawBackground(painter, rect);
int top = ceil(rect.top());
int bottom = floor(rect.bottom());
int left = floor(rect.left());
int right = ceil(rect.right());
QPen gridPen(QColor("#323232"));
painter->setPen(gridPen);
QList<QLine> lines;
for (int y = top - (top % gridSize_); y <= bottom; y += gridSize_) {
lines.append(QLine(left, y, right, y));
}
for (int x = left - (left % gridSize_); x <= right; x += gridSize_) {
lines.append(QLine(x, bottom, x, top));
}
painter->drawLines(lines);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <QGraphicsScene>
class NetworkGraphicsScene
: public QGraphicsScene
{
public:
NetworkGraphicsScene();
private:
uint sceneWidth_;
uint sceneHeight_;
uint gridSize_;
protected:
void drawBackground(QPainter *painter, const QRectF &rect) override;
};

View File

@@ -0,0 +1,132 @@
#include "Gui/Network/NetworkGraphicsView.h"
#include <QGraphicsItem>
#include "Gui/Network/Network.h"
#include "Gui/Network/NetworkGraphicsScene.h"
#include "Gui/Network/SocketGraphic.h"
#include <iostream>
#include <QMouseEvent>
#include <QScrollBar>
#include <qgraphicsitem.h>
#include <qobject.h>
#include <typeinfo>
NetworkGraphicsView::NetworkGraphicsView(QWidget *parent, Network* network, QGraphicsScene* scene)
: QGraphicsView(parent), scene_{scene}, network_{network}
{
setScene(scene_);
setMouseTracking(true);
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
initUI();
}
void NetworkGraphicsView::initUI()
{
// zoom from mouse
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
// disable scroll bars
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
//
setViewportUpdateMode(ViewportUpdateMode::FullViewportUpdate);
}
void NetworkGraphicsView::mouseReleaseEvent(QMouseEvent *event) {
QGraphicsView::mouseReleaseEvent(event);
// pass event to parent
if (parentWidget()) {
QMouseEvent *eventCopy = new QMouseEvent(
event->type(),
event->position(),
event->scenePosition(),
event->globalPosition(),
event->button(),
event->buttons(),
event->modifiers()
);
QCoreApplication::postEvent(parentWidget(), eventCopy);
}
}
void NetworkGraphicsView::mousePressEvent(QMouseEvent *event)
{
if(
event->button() == Qt::MiddleButton
)
{
panStartPos = event->pos();
event->accept();
return;
}
QGraphicsView::mousePressEvent(event);
// pass event to parent
// if (parentWidget()) {
// QMouseEvent *eventCopy = new QMouseEvent(
// event->type(),
// event->position(),
// event->scenePosition(),
// event->globalPosition(),
// event->button(),
// event->buttons(),
// event->modifiers()
// );
// QCoreApplication::postEvent(parentWidget(), eventCopy);
// }
}
// void NetworkView::mouseReleaseEvent(QMouseEvent *event)
// {
// if(
// event->button() & Qt::MiddleButton
// )
// {
// panStartPos = QPointF(0,0);
// }
// }
void NetworkGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
network_->mouseMoved(event);
// pan view
if( event->buttons() & Qt::MiddleButton)
{
QPointF pos = event->pos();
QPointF delta = pos-panStartPos;
float speed = 1.0f;
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x());
verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y());
panStartPos = event->pos();
event->accept();
return;
}
QGraphicsView::mouseMoveEvent(event);
}
void NetworkGraphicsView::wheelEvent(QWheelEvent *event)
{
int delta = event->angleDelta().y();
if(delta > 0)
{
scale(1.1, 1.1);
}
else if(delta < 0)
{
scale(0.9, 0.9);
}
event->accept();
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <qgraphicsitem.h>
#include <qwidget.h>
#include <QGraphicsView>
#include <QGraphicsScene>
class Network;
class NetworkGraphicsView
: public QGraphicsView
{
public:
NetworkGraphicsView(QWidget *parent = nullptr, Network* network=nullptr, QGraphicsScene* scene = nullptr);
QSize sizeHint() const override { return QSize(-1, -1); }
private:
QPointF panStartPos;
void initUI();
QGraphicsScene* scene_;
Network* network_;
protected:
void mouseMoveEvent(QMouseEvent *mouseEvent) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
QGraphicsItem* getItemAtClick(QMouseEvent *event);
void wheelEvent(QWheelEvent *event) override;
// void mouseReleaseEvent(QMouseEvent *event) override;
};

View File

@@ -0,0 +1,140 @@
#include "Gui/Network/NodeEdgeGraphic.h"
#include <QTextDocument>
#include "Gui/Network/SocketGraphic.h"
#include <iostream>
#include <qgraphicsitem.h>
#include <QGraphicsScene>
#include <QGraphicsSceneHoverEvent>
NodeEdgeGraphic::NodeEdgeGraphic(SocketGraphic* socket1, SocketGraphic* socket2, QGraphicsItem *parent)
: QGraphicsItem(parent), socket1_{socket1}, socket2_{socket2}, defaultColor_{QColor("white")}
{
setAcceptHoverEvents(true);
setZValue(-1);
color_=defaultColor_;
defaultPen_=QPen(defaultColor_);
defaultPen_.setCapStyle(Qt::RoundCap);
deleteHighlightPen_.setCapStyle(Qt::RoundCap);
deleteHighlightPen_.setWidth(2);
updateDeleteHighlightPen();
socket1_->addEdge(this);
socket2_->addEdge(this);
}
void NodeEdgeGraphic::updateDeleteHighlightPen()
{
QLinearGradient gradient(pos1_, hoverPos_);
gradient.setColorAt(0.0, QColor(255, 74, 74, 200));
gradient.setColorAt(1, QColor(255, 74, 74, 50));
// gradient.setColorAt(1.0, QColor(255, 74, 74, 200));
deleteHighlightPen_.setBrush(QBrush(gradient));
}
NodeEdgeGraphic::~NodeEdgeGraphic()
{
std::cout << "edge destructor\n";
cleanUp();
std::cout << "destructor finished\n";
}
void NodeEdgeGraphic::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
hoverPos_ = event->scenePos();
if(deleteHighlight_)
{
updateDeleteHighlightPen();
update();
}
}
void NodeEdgeGraphic::updatePath()
{
qreal cubicStrength = 40;
path_.clear();
path_.moveTo(pos1_);
path_.cubicTo(pos1_-QPoint(0,cubicStrength), pos2_+QPoint(0,cubicStrength), pos2_);
updateDeleteHighlightPen();
update();
}
void NodeEdgeGraphic::setPos(QPointF pos1, QPointF pos2)
{
prepareGeometryChange();
pos1_ = pos1;
pos2_ = pos2;
updatePath();
}
void NodeEdgeGraphic::setDeleteHighlight(bool enable)
{
deleteHighlight_=enable;
update();
}
void NodeEdgeGraphic::setStartPos(QPointF pos)
{
prepareGeometryChange();
pos1_ = pos;
updatePath();
}
void NodeEdgeGraphic::setEndPos(QPointF pos)
{
prepareGeometryChange();
pos2_ = pos;
updatePath();
}
QRectF NodeEdgeGraphic::boundingRect() const
{
// std::cout << "bounds set" << socket1_->scenePos().x() << " " << socket1_->scenePos().y() << " " << socket2_->scenePos().x() << " " << socket2_->scenePos().y() << "\n";
// QRectF boundRect_ = QRectF(socket1_->scenePos(), socket1_->scenePos()).normalized();
QRectF boundRect_ = QRectF(pos1_, pos2_).normalized();
boundRect_.adjust(-padding_,-padding_,padding_,padding_);
return boundRect_;
}
QPainterPath NodeEdgeGraphic::shape() const{
QPainterPathStroker stroker;
stroker.setWidth(padding_);
return stroker.createStroke(path_);
}
// void NodeEdgeGraphic::setColor(QColor color)
// {
// std::cout << "color set to: " << color.name().toStdString() << "\n";
// color_ = color;
// pen_.setColor(color_);
// update();
// }
// void NodeEdgeGraphic::useDefaultColor()
// {
// setColor(defaultColor_);
// }
void NodeEdgeGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// std::cout << "painting\n";
painter->setPen(deleteHighlight_ ? deleteHighlightPen_ : defaultPen_);
painter->drawPath(path_);
}
void NodeEdgeGraphic::cleanUp()
{
// these probably aren't necessary but i'm trying to fix a bug
prepareGeometryChange();
update();
scene()->update();
scene()->removeItem(this);
socket1_->removeEdge(this);
socket2_->removeEdge(this);
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <QGraphicsItem>
#include "Gui/Network/SocketGraphic.h"
#include <QPainter>
class NodeEdgeGraphic
: public QGraphicsItem
{
public:
NodeEdgeGraphic(SocketGraphic* socket1, SocketGraphic* socket2, QGraphicsItem *parent = nullptr);
~NodeEdgeGraphic();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QPainterPath shape() const override;
// void setColor(QColor color);
// void useDefaultColor();
void updateDeleteHighlightPen();
void setPos(QPointF pos1, QPointF pos2);
void setStartPos(QPointF pos);
void setEndPos(QPointF pos);
void cleanUp();
void setDeleteHighlight(bool enable);
QPen deleteHighlightPen_;
QPen defaultPen_;
bool deleteHighlight_=false;
private:
SocketGraphic* socket1_;
SocketGraphic* socket2_;
QColor color_;
QColor defaultColor_;
QPointF pos1_;
QPointF pos2_;
QPainterPath path_;
QRectF boundRect_;
qreal padding_=40;
QPointF hoverPos_;
void updatePath();
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
};

View File

@@ -0,0 +1,249 @@
#include "Gui/Network/NodeGraphic.h"
#include <QTextDocument>
#include <iostream>
#include <qgraphicsitem.h>
#include <qnamespace.h>
#include <stdexcept>
#include <string>
#include "Engine/Network/NetworkManager.h"
#include "Engine/Operator/GeometryOperator.h"
#include "Engine/Types.h"
#include "Gui/Network/DisplayFlagButton.h"
#include "Gui/Network/SocketGraphic.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSvgItem>
#include "Gui/Network/NodeIconGraphic.h"
NodeGraphic::NodeGraphic(enzo::nt::OpId id, QGraphicsItem *parent)
: QGraphicsItem(parent), opId_{id}
{
socketSize_ = 3;
titlePadding_=1;
titleText_ = "Attr_Del_1";
subTitleText_ = "Attribute Delete";
constexpr int height = 27;
constexpr int width = 100;
bodyRect_ = QRect(-width*0.5f, -height*0.5f, width, height);
iconScale_=height*0.55;
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
initFonts();
initIcon();
initSockets();
initFlagButtons();
}
void NodeGraphic::initFonts()
{
// declare fonts
titleFont_ = QFont();
titleFont_.setPixelSize(8);
subTitleFont_ = QFont();
subTitleFont_.setPixelSize(5);
// compute text positions
QRectF titleBounds = QFontMetricsF(titleFont_).boundingRect(titleText_.c_str());
QRectF subTitleBounds = QFontMetricsF(subTitleFont_).boundingRect(subTitleText_.c_str());
float titleOffsetX = (titleBounds.width()-bodyRect_.width()-iconScale_)*0.5f;
float titleOffsetY = subTitleBounds.height()*0.5f+titlePadding_+(-(subTitleBounds.height()*0.5+titleBounds.height()+titlePadding_)+bodyRect_.height())*0.5f;
// float titleOffsetY = (bodyRect_.height())*0.5f;
// titleOffsetY -= subTitleBounds.height()*0.5f;
float subTitleOffsetX = titleOffsetX;
float subTitleOffsetY = (-(subTitleBounds.height()*0.5+titleBounds.height()+titlePadding_)+bodyRect_.height())*0.5f;
titleRect_ = bodyRect_.adjusted(-titleOffsetX, titleOffsetY, -titleOffsetX, titleOffsetY);
subTitleRect_ = bodyRect_.adjusted(-subTitleOffsetX, subTitleOffsetY, -subTitleOffsetX, subTitleOffsetY);
}
void NodeGraphic::initIcon()
{
icon_ = new NodeIconGraphic(":/node-icons/grid.svg", this);
// icon_ = new NodeIconGraphic("/home/parker/MyRepos/masters/static/icons/icon-main-white.svg", this);
icon_->setScale(1.0f/icon_->boundingRect().width()*iconScale_);
// icon_->setScale(0.01);
icon_->setPos(titleRect_.left()-iconScale_-iconPadding_, -iconScale_*0.5f);
}
void NodeGraphic::initFlagButtons()
{
displayFlagButton_ = new DisplayFlagButton(this);
float padding = 2;
displayFlagButton_->setPos(QPointF(bodyRect_.right()-displayFlagButton_->getWidth()/2.0f-padding, bodyRect_.center().y()));
}
void NodeGraphic::initSockets()
{
enzo::nt::GeometryOperator& op = enzo::nt::NetworkManager::getGeoOperator(opId_);
for(int i=0, max=op.getMaxInputs(); i<max; ++i)
{
auto* socketInput = new SocketGraphic(enzo::nt::SocketIOType::Input, opId_, i, this);
socketInput->setPos(getSocketPosition(i, enzo::nt::SocketIOType::Input));
inputs_.push_back(socketInput);
}
for(int i=0, max=op.getMaxOutputs(); i<max; ++i)
{
auto* socketOutput = new SocketGraphic(enzo::nt::SocketIOType::Output, opId_, i, this);
socketOutput->setPos(getSocketPosition(i, enzo::nt::SocketIOType::Output));
outputs_.push_back(socketOutput);
}
}
// void setInputEdge(NodeEdgeGraphic* edge, int indx)
// {
// }
// void setOutputEdge(NodeEdgeGraphic* edge, int indx)
// {
// }
// void NodeGraphic::addEdge(NodeEdgeGraphic* edge)
// {
// edges_.push_back(edge);
// }
SocketGraphic* NodeGraphic::getInput(int indx) const
{
if(inputs_.size()==0)
{
throw std::out_of_range("Can't access inputs when node has no inputs: " + std::to_string(indx));
}
else if(indx>inputs_.size()-1)
{
throw std::out_of_range("Can't access input: " + std::to_string(indx));
}
return inputs_.at(indx);
}
SocketGraphic* NodeGraphic::getOutput(int indx) const
{
if(outputs_.size()==0)
{
throw std::out_of_range("Can't access outputs when node has no outputs: " + std::to_string(indx));
}
else if(indx>inputs_.size()-1)
{
throw std::out_of_range("Can't access input: " + std::to_string(indx));
}
return outputs_.at(indx);
}
QRectF NodeGraphic::boundingRect() const
{
QRectF boundRect = bodyRect_;
float padding = 0;
boundRect.adjust(-padding, -padding, padding, padding);
return boundRect;
}
void NodeGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// default outline
QPen defaultPen = Qt::NoPen;
defaultPen.setWidth(1);
// outline when selected
QPen selectedPen = QPen("#edd044");
// choose outline
if(isSelected()) painter->setPen(selectedPen);
else painter->setPen(defaultPen);
// set fill
QBrush whiteBrush = QBrush("white");
painter->setBrush(QBrush(QColor("#1b1b1b")));
painter->drawRoundedRect(bodyRect_, 5, 5);
painter->setPen(QPen(QColor("white")));
painter->setFont(titleFont_);
// painter->setPen(QPen(QColor("#d2d2d2")));
painter->setPen(QPen(QColor("white")));
painter->drawText(titleRect_, Qt::AlignLeft, titleText_.c_str());
painter->setFont(subTitleFont_);
painter->drawText(subTitleRect_, Qt::AlignLeft, subTitleText_.c_str());
}
// void NodeGraphic::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
// {
// QGraphicsItem::mouseMoveEvent(event);
// updatePositions(event->scenePos());
// }
// void NodeGraphic::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
// {
// updatePositions(event->scenePos());
// QGraphicsItem::mouseReleaseEvent(event);
// }
void NodeGraphic::updatePositions()
{
for(int socketIndex=0; socketIndex<inputs_.size(); ++socketIndex)
{
inputs_[socketIndex]->posChanged(getSocketScenePosition(socketIndex, enzo::nt::SocketIOType::Input));
}
for(int socketIndex=0; socketIndex<outputs_.size(); ++socketIndex)
{
outputs_[socketIndex]->posChanged(getSocketScenePosition(socketIndex, enzo::nt::SocketIOType::Output));
}
}
QPointF NodeGraphic::getSocketPosition(int socketIndex, enzo::nt::SocketIOType socketType)
{
enzo::nt::GeometryOperator& op = enzo::nt::NetworkManager::getGeoOperator(opId_);
int maxSocketNumber = socketType==enzo::nt::SocketIOType::Input ? op.getMaxInputs() : op.getMaxOutputs();
float socketSpread = socketSize_*1.5*maxSocketNumber;
float xPos, yPos;
xPos = bodyRect_.center().x();
yPos = socketType == enzo::nt::SocketIOType::Input ? bodyRect_.top() : bodyRect_.bottom();
xPos += ((socketIndex/static_cast<float>(maxSocketNumber-1))-0.5)*2*socketSpread;
return QPointF(xPos, yPos);
}
QPointF NodeGraphic::getSocketScenePosition(int socketIndex, enzo::nt::SocketIOType socketType)
{
return this->pos()+getSocketPosition(socketIndex, socketType);
}
enzo::nt::OpId NodeGraphic::getOpId() const
{
return opId_;
}
void NodeGraphic::setDisplayFlag(bool state)
{
displayFlagButton_->setEnabled(state);
}
QRectF NodeGraphic::getBodyRect()
{
return bodyRect_;
}
QVariant NodeGraphic::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
QVariant returnVal = QGraphicsItem::itemChange(change, value);
if (change == ItemPositionHasChanged) {
updatePositions();
};
return returnVal;
}

View File

@@ -0,0 +1,76 @@
#pragma once
#include <QGraphicsItem>
#include <QPainter>
#include "Engine/Types.h"
#include "Gui/Network/DisplayFlagButton.h"
#include "Gui/Network/SocketGraphic.h"
#include "Gui/Network/NodeIconGraphic.h"
#include "Gui/Network/NodeEdgeGraphic.h"
#include <iostream>
class NodeGraphic
: public QGraphicsItem
{
public:
NodeGraphic(enzo::nt::OpId id, QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
SocketGraphic* getInput(int indx) const;
SocketGraphic* getOutput(int indx) const;
enzo::nt::OpId getOpId() const;
QPointF getSocketPosition(int socketIndex, enzo::nt::SocketIOType socketType);
QPointF getSocketScenePosition(int socketIndex, enzo::nt::SocketIOType socketType);
QRectF getBodyRect();
void setDisplayFlag(bool state);
// void addEdge(NodeEdgeGraphic* edge);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
// void setInputEdge(NodeEdgeGraphic* edge, int indx);
// void setOutputEdge(NodeEdgeGraphic* edge, int indx);
private:
void initSockets();
void initFlagButtons();
void initIcon();
void initFonts();
enzo::nt::OpId opId_;
std::vector<SocketGraphic*> inputs_;
std::vector<SocketGraphic*> outputs_;
// std::vector<NodeEdgeGraphic*> edges_;
std::string titleText_="";
std::string subTitleText_="";
int maxTitleLen_=10;
QRectF bodyRect_;
int socketSize_ = 1;
int inputSocketCnt_=0;
int outputSocketCnt_=0;
NodeIconGraphic* icon_;
int iconScale_;
float iconPadding_ = 5;
QGraphicsItem* test_;
QFont titleFont_;
QFont subTitleFont_;
int titlePadding_;
QRectF titleRect_;
QRectF subTitleRect_;
DisplayFlagButton* displayFlagButton_;
void updatePositions();
protected:
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
// void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
// void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
};

View File

@@ -0,0 +1,17 @@
#include "Gui/Network/NodeIconGraphic.h"
#include <qgraphicssvgitem.h>
#include <QBrush>
#include <QPainter>
NodeIconGraphic::NodeIconGraphic(const QString &fileName, QGraphicsItem *parent)
: QGraphicsSvgItem(fileName, parent)
{
}
// void NodeIconGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
// {
//
// this->setProperty("color", QColor("red"));
// QGraphicsSvgItem::paint(painter, option, widget);
// }

View File

@@ -0,0 +1,12 @@
#pragma once
#include <QGraphicsSvgItem>
class NodeIconGraphic
: public QGraphicsSvgItem
{
public:
NodeIconGraphic(const QString &fileName, QGraphicsItem *parent = nullptr);
protected:
// void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
};

View File

@@ -0,0 +1,116 @@
#include "Gui/Network/SocketGraphic.h"
#include <QTextDocument>
#include <iostream>
#include <qgraphicsitem.h>
#include "Gui/Network/NodeEdgeGraphic.h"
SocketGraphic::SocketGraphic(enzo::nt::SocketIOType type, enzo::nt::OpId opId, unsigned int socketIndex, QGraphicsItem *parent)
: QGraphicsItem(parent), type_{type}, opId_{opId}, socketIndex_{socketIndex}
{
brushActive_ = QBrush("white");
brushInactive_ = QBrush("#9f9f9f");
socketSize_ = 3;
setAcceptHoverEvents(true);
initBoundingBox();
}
unsigned int SocketGraphic::getIndex() const
{
return socketIndex_;
}
void SocketGraphic::addEdge(NodeEdgeGraphic* edge)
{
std::cout << "adding edge\n";
edges_.insert(edge);
}
void SocketGraphic::removeEdge(NodeEdgeGraphic* edge)
{
std::cout << "removing edge\n";
std::cout << "before size: " << edges_.size() << "\n";
edges_.erase(edge);
std::cout << "after size: " << edges_.size() << "\n";
// auto it = find(edges_.begin(), edges_.end(), edge);
// if(it!=edges_.end())
// {
// edges_.erase(it);
// }
}
void SocketGraphic::initBoundingBox()
{
boundRect_ = QRect(
-socketSize_/2.0f*paddingScale_,
-socketSize_/2.0f*paddingScale_,
socketSize_*paddingScale_,
socketSize_*paddingScale_
);
}
void SocketGraphic::posChanged(QPointF pos)
{
for(auto* edge : edges_)
{
// edge->setPos(startSocket_->scenePos(), socket->scenePos());
if(type_==enzo::nt::SocketIOType::Input)
{
edge->setStartPos(pos);
}
else if(type_==enzo::nt::SocketIOType::Output)
{
edge->setEndPos(pos);
}
}
}
enzo::nt::OpId SocketGraphic::getOpId() const
{
return opId_;
}
QRectF SocketGraphic::boundingRect() const
{
return boundRect_;
}
QPainterPath SocketGraphic::shape() const{
QPainterPath path;
QPointF startPt(boundRect_.center().x(), type_==enzo::nt::SocketIOType::Input ? boundRect_.top() : boundRect_.bottom());
path.moveTo(startPt);
path.arcTo(boundRect_, 0, type_==enzo::nt::SocketIOType::Input ? 180 : -180);
path.lineTo(boundRect_.right(), boundRect_.center().y());
path.closeSubpath();
return path;
}
enzo::nt::SocketIOType SocketGraphic::getIO() { return type_; }
void SocketGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::NoPen);
painter->setBrush(hovered_ ? brushActive_ : brushInactive_);
painter->drawEllipse(QPoint(0,0), socketSize_, socketSize_);
// painter->drawRect(boundRect_);
}
void SocketGraphic::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
hovered_ = true;
update();
}
void SocketGraphic::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
hovered_ = false;
update();
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "Engine/Types.h"
#include <QGraphicsItem>
#include <QPainter>
#include <unordered_set>
class NodeEdgeGraphic;
class SocketGraphic
: public QGraphicsItem
{
public:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
SocketGraphic(enzo::nt::SocketIOType type, enzo::nt::OpId opId, unsigned int socketIndex, QGraphicsItem *parent = nullptr);
enzo::nt::SocketIOType getIO();
void addEdge(NodeEdgeGraphic* edge);
void removeEdge(NodeEdgeGraphic* edge);
void posChanged(QPointF pos);
QPainterPath shape() const override;
enzo::nt::OpId getOpId() const;
unsigned int getIndex() const;
private:
int socketSize_ = 1;
unsigned int socketIndex_;
QBrush brushInactive_;
QBrush brushActive_;
bool hovered_=false;
enzo::nt::SocketIOType type_;
std::unordered_set<NodeEdgeGraphic*> edges_;
qreal paddingScale_=20;
QRectF boundRect_;
enzo::nt::OpId opId_;
void initBoundingBox();
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
};