#include "gui/network/NodeGraphic.h" #include #include #include #include #include #include #include "Engine/Network/NetworkManager.h" #include "Engine/Operator/GeometryOperator.h" #include "gui/network/DisplayFlagButton.h" #include "gui/network/SocketGraphic.h" #include #include #include #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; setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); 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() { auto nm = enzo::nt::NetworkManager::getInstance(); enzo::nt::GeometryOperator& op = nm->getGeoOperator(opId_); for(int i=0, max=op.getMaxInputs(); isetPos(getSocketPosition(i, enzo::nt::SocketIOType::Input)); inputs_.push_back(socketInput); } for(int i=0, max=op.getMaxOutputs(); isetPos(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(QPointF pos) { // NOTE: in the future I might store socket ids as internal member variables, // but for now I'm just going based on order for(int socketIndex=0; socketIndexposChanged(getSocketScenePosition(socketIndex, enzo::nt::SocketIOType::Input)); } for(int socketIndex=0; socketIndexposChanged(getSocketScenePosition(socketIndex, enzo::nt::SocketIOType::Output)); } } QPointF NodeGraphic::getSocketPosition(int socketIndex, enzo::nt::SocketIOType socketType) { auto nm = enzo::nt::NetworkManager::getInstance(); enzo::nt::GeometryOperator& op = nm->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(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); } QRectF NodeGraphic::getBodyRect() { return bodyRect_; } // QVariant NodeGraphic::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) // { // if (change == ItemPositionChange && scene()) { // for(auto socket : inputs_) // { // socket->posChanged(value.toPointF()); // } // for(auto socket : outputs_) // { // socket->posChanged(value.toPointF()); // } // }; // return QGraphicsItem::itemChange(change, value); // }