diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 818f55095..d5e85fcfb 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -1535,7 +1535,7 @@ void NodeView::PositionNewEdge(const QPoint &pos) if (highlight_index >= 0) { create_edge_dst_input_ = create_edge_dst_->GetInputAtIndex(highlight_index); create_edge_->SetPoints(create_edge_src_->GetOutputPoint(), - create_edge_dst_->GetInputPoint(create_edge_dst_input_.input(), create_edge_dst_input_.element(), create_edge_src_->pos()), + create_edge_dst_->GetInputPoint(create_edge_dst_input_.input(), create_edge_dst_input_.element()), true); } else { create_edge_dst_input_.Reset(); diff --git a/app/widget/nodeview/nodeviewcommon.h b/app/widget/nodeview/nodeviewcommon.h index 03c5f8dcf..d0541fba4 100644 --- a/app/widget/nodeview/nodeviewcommon.h +++ b/app/widget/nodeview/nodeviewcommon.h @@ -44,6 +44,16 @@ public: } } + static bool IsFlowVertical(FlowDirection dir) + { + return dir == kTopToBottom || dir == kBottomToTop; + } + + static bool IsFlowHorizontal(FlowDirection dir) + { + return dir == kLeftToRight || dir == kRightToLeft; + } + static bool DirectionsAreOpposing(FlowDirection a, FlowDirection b) { return ((a == NodeViewCommon::kLeftToRight && b == NodeViewCommon::kRightToLeft) || (a == NodeViewCommon::kRightToLeft && b == NodeViewCommon::kLeftToRight) diff --git a/app/widget/nodeview/nodeviewcontext.cpp b/app/widget/nodeview/nodeviewcontext.cpp index 0e8262b3e..db22be143 100644 --- a/app/widget/nodeview/nodeviewcontext.cpp +++ b/app/widget/nodeview/nodeviewcontext.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -21,9 +22,6 @@ namespace olive { NodeViewContext::NodeViewContext(QGraphicsItem *item) : super(item) { - setFlag(ItemIsMovable); - setFlag(ItemIsSelectable); - // Set default label text SetContext(nullptr); } @@ -101,10 +99,13 @@ void NodeViewContext::UpdateRect() QFontMetricsF fm(f); qreal lbl_offset = GetTextOffset(fm); - QRectF rect = childrenBoundingRect(); + QRectF cbr = childrenBoundingRect(); + QRectF rect = cbr; int pad = NodeViewItem::DefaultItemHeight(); rect.adjust(-pad, - lbl_offset*2 - fm.height() - pad, pad, pad); setRect(rect); + + last_titlebar_height_ = rect.y() + (cbr.y() - rect.y()); } void NodeViewContext::SetFlowDirection(NodeViewCommon::FlowDirection dir) @@ -164,6 +165,16 @@ QVariant NodeViewContext::itemChange(GraphicsItemChange change, const QVariant & return super::itemChange(change, value); } +void NodeViewContext::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + bool clicked_inside_titlebar = (event->pos().y() < last_titlebar_height_); + + setFlag(ItemIsMovable, clicked_inside_titlebar); + setFlag(ItemIsSelectable, clicked_inside_titlebar); + + super::mousePressEvent(event); +} + NodeViewEdge* NodeViewContext::AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to) { NodeViewEdge* edge_ui = new NodeViewEdge(output, input, from, to, this); diff --git a/app/widget/nodeview/nodeviewcontext.h b/app/widget/nodeview/nodeviewcontext.h index a5141e32b..cf35b6fd2 100644 --- a/app/widget/nodeview/nodeviewcontext.h +++ b/app/widget/nodeview/nodeviewcontext.h @@ -30,6 +30,8 @@ public: protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override; + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override; + private: NodeViewEdge *AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to); @@ -41,6 +43,8 @@ private: bool curved_edges_; + int last_titlebar_height_; + }; } diff --git a/app/widget/nodeview/nodeviewedge.cpp b/app/widget/nodeview/nodeviewedge.cpp index 5498fbefb..f6df8ce73 100644 --- a/app/widget/nodeview/nodeviewedge.cpp +++ b/app/widget/nodeview/nodeviewedge.cpp @@ -60,7 +60,7 @@ void NodeViewEdge::Adjust() { // Draw a line between the two SetPoints(from_item()->GetOutputPoint(), - to_item()->GetInputPoint(input_.input(), input_.element(), from_item()->pos()), + to_item()->GetInputPoint(input_.input(), input_.element()), to_item()->IsExpanded()); } diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index 2eb766863..520d2c961 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -67,7 +67,6 @@ NodeViewItem::NodeViewItem(QGraphicsItem *parent) : title_bar_rect_ = QRectF(-widget_width/2, -widget_height/2, widget_width, widget_height); setRect(title_bar_rect_); - input_connector_ = new NodeViewItemConnector(this); output_connector_ = new NodeViewItemConnector(this); } @@ -219,6 +218,8 @@ void NodeViewItem::SetNode(Node *n) node_inputs_.clear(); + ClearInputConnectors(); + if (node_) { node_->Retranslate(); @@ -228,7 +229,7 @@ void NodeViewItem::SetNode(Node *n) } } - input_connector_->setVisible(!node_inputs_.isEmpty()); + UpdateInputConnectors(); connect(n, &Node::LabelChanged, this, &NodeViewItem::NodeAppearanceChanged); connect(n, &Node::ColorChanged, this, &NodeViewItem::NodeAppearanceChanged); @@ -246,7 +247,6 @@ void NodeViewItem::SetExpanded(bool e, bool hide_titlebar) expanded_ = e; hide_titlebar_ = hide_titlebar; - input_connector_->setVisible(!expanded_); if (expanded_ && !node_inputs_.isEmpty()) { // Create new rect @@ -263,13 +263,15 @@ void NodeViewItem::SetExpanded(bool e, bool hide_titlebar) setRect(title_bar_rect_); } - update(); + UpdateInputConnectorFlowDirections(); UpdateConnectorPositions(); ReadjustAllEdges(); UpdateContextRect(); + + update(); } void NodeViewItem::ToggleExpanded() @@ -403,6 +405,8 @@ QVariant NodeViewItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons void NodeViewItem::ReadjustAllEdges() { + UpdateInputConnectorFlowDirections(); + UpdateInputConnectorPositions(); foreach (NodeViewEdge* edge, edges_) { edge->Adjust(); } @@ -502,13 +506,15 @@ QRectF NodeViewItem::GetInputRect(int index) const return r; } -QPointF NodeViewItem::GetInputPoint(const QString &input, int element, const QPointF& source_pos) const +QPointF NodeViewItem::GetInputPoint(const QString &input, int element) const { - if (expanded_) { - return pos() + GetInputPointInternal(node_inputs_.indexOf(input), source_pos); - } else { - return pos() + input_connector_->pos(); + int index = node_inputs_.indexOf(input); + + if (index < 0 || index >= int(input_connectors_.size())) { + return QPointF(); } + + return pos() + input_connectors_[index]->pos(); } QPointF NodeViewItem::GetOutputPoint() const @@ -539,64 +545,101 @@ void NodeViewItem::SetFlowDirection(NodeViewCommon::FlowDirection dir) { flow_dir_ = dir; - input_connector_->SetFlowDirection(dir); + UpdateInputConnectorFlowDirections(); output_connector_->SetFlowDirection(dir); UpdateConnectorPositions(); UpdateNodePosition(); } -QPointF NodeViewItem::GetInputPointInternal(int index, const QPointF& source_pos) const -{ - QRectF input_rect = GetInputRect(index); - - Qt::Orientation flow_orientation = NodeViewCommon::GetFlowOrientation(flow_dir_); - - if (flow_orientation == Qt::Horizontal || IsExpanded()) { - if (flow_dir_ == NodeViewCommon::kLeftToRight - || (flow_orientation == Qt::Vertical && source_pos.x() < pos().x())) { - return QPointF(input_rect.left(), input_rect.center().y()); - } else { - return QPointF(input_rect.right(), input_rect.center().y()); - } - } else { - if (flow_dir_ == NodeViewCommon::kTopToBottom) { - return QPointF(input_rect.center().x(), input_rect.top()); - } else { - return QPointF(input_rect.center().x(), input_rect.bottom()); - } - } -} - void NodeViewItem::UpdateNodePosition() { setPos(NodeToScreenPoint(cached_node_pos_, flow_dir_)); } +void NodeViewItem::UpdateInputConnectors() +{ + int old_sz = input_connectors_.size(); + + input_connectors_.resize(node_inputs_.size()); + for (size_t i=old_sz; i(this); + } +} + +void NodeViewItem::ClearInputConnectors() +{ + input_connectors_.clear(); +} + void NodeViewItem::UpdateConnectorPositions() { - QRectF output_rect = output_connector_->boundingRect(); + UpdateInputConnectorPositions(); switch (flow_dir_) { case NodeViewCommon::kLeftToRight: - input_connector_->setPos(rect().left() - output_rect.width(), rect().center().y()); - output_connector_->setPos(rect().right(), rect().center().y()); + output_connector_->setPos(rect().right(), title_bar_rect_.center().y()); break; case NodeViewCommon::kRightToLeft: - input_connector_->setPos(rect().right() + output_rect.width(), rect().center().y()); - output_connector_->setPos(rect().left(), rect().center().y()); + output_connector_->setPos(rect().left(), title_bar_rect_.center().y()); break; case NodeViewCommon::kTopToBottom: - input_connector_->setPos(rect().center().x(), rect().top() - output_rect.height()); output_connector_->setPos(rect().center().x(), rect().bottom()); break; case NodeViewCommon::kBottomToTop: - input_connector_->setPos(rect().center().x(), rect().bottom() + output_rect.height()); output_connector_->setPos(rect().center().x(), rect().top()); break; } } +void NodeViewItem::UpdateInputConnectorPositions() +{ + QRectF output_rect = output_connector_->boundingRect(); + + // Input connector flow directions change conditionally + for (size_t i=0; isetPos(rect().left() - output_rect.width(), GetInputRect(i).center().y()); + break; + case NodeViewCommon::kRightToLeft: + input_connectors_[i]->setPos(rect().right() + output_rect.width(), GetInputRect(i).center().y()); + break; + case NodeViewCommon::kTopToBottom: + input_connectors_[i]->setPos(rect().center().x(), rect().top() - output_rect.height()); + break; + case NodeViewCommon::kBottomToTop: + input_connectors_[i]->setPos(rect().center().x(), rect().bottom() + output_rect.height()); + break; + } + } +} + +void NodeViewItem::UpdateInputConnectorFlowDirections() +{ + for (size_t i=0; iSetFlowDirection(GetFlowDirectionForInput(i)); + } +} + +NodeViewCommon::FlowDirection NodeViewItem::GetFlowDirectionForInput(int index) +{ + if (!expanded_ || NodeViewCommon::IsFlowHorizontal(flow_dir_)) { + return flow_dir_; + } else { + foreach (NodeViewEdge *edge, edges_) { + if (edge->input().input() == node_inputs_.at(index)) { + if (edge->from_item()->x() < this->x()) { + return NodeViewCommon::kLeftToRight; + } else { + return NodeViewCommon::kRightToLeft; + } + } + } + return NodeViewCommon::kLeftToRight; + } +} + void NodeViewItem::NodeAppearanceChanged() { update(); diff --git a/app/widget/nodeview/nodeviewitem.h b/app/widget/nodeview/nodeviewitem.h index bd2cd7ac1..c1ff35387 100644 --- a/app/widget/nodeview/nodeviewitem.h +++ b/app/widget/nodeview/nodeviewitem.h @@ -80,7 +80,7 @@ public: /** * @brief Returns GLOBAL point that edges should connect to for any NodeParam member of this object */ - QPointF GetInputPoint(const QString& input, int element, const QPointF &source_pos) const; + QPointF GetInputPoint(const QString& input, int element) const; QPointF GetOutputPoint() const; @@ -156,18 +156,22 @@ private: */ QRectF GetInputRect(int index) const; - /** - * @brief Returns local point that edges should connect to for a NodeInput in array node_inputs_[index] - */ - QPointF GetInputPointInternal(int index, const QPointF &source_pos) const; - /** * @brief Internal update function when logical position changes */ void UpdateNodePosition(); + void UpdateInputConnectors(); + + void ClearInputConnectors(); + void UpdateConnectorPositions(); + void UpdateInputConnectorPositions(); + void UpdateInputConnectorFlowDirections(); + + NodeViewCommon::FlowDirection GetFlowDirectionForInput(int index); + /** * @brief Reference to attached Node */ @@ -203,7 +207,7 @@ private: bool prevent_removing_; - NodeViewItemConnector *input_connector_; + std::vector > input_connectors_; NodeViewItemConnector *output_connector_; bool label_as_output_;