further improved new node view
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QBrush>
|
||||
#include <QCoreApplication>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPen>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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<input_connectors_.size(); i++) {
|
||||
input_connectors_[i] = std::make_unique<NodeViewItemConnector>(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; i<input_connectors_.size(); i++) {
|
||||
switch (GetFlowDirectionForInput(i)) {
|
||||
case NodeViewCommon::kLeftToRight:
|
||||
input_connectors_[i]->setPos(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; i<input_connectors_.size(); i++) {
|
||||
input_connectors_[i]->SetFlowDirection(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();
|
||||
|
||||
@@ -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<std::unique_ptr<NodeViewItemConnector> > input_connectors_;
|
||||
NodeViewItemConnector *output_connector_;
|
||||
|
||||
bool label_as_output_;
|
||||
|
||||
Reference in New Issue
Block a user