nodeview: allow users to place a node on an edge to automatically connect it
between the two nodes UI convenience. Edge highlights when the cursor is in range to perform this action.
This commit is contained in:
@@ -29,7 +29,8 @@
|
||||
NodeView::NodeView(QWidget *parent) :
|
||||
QGraphicsView(parent),
|
||||
graph_(nullptr),
|
||||
attached_item_(nullptr)
|
||||
attached_item_(nullptr),
|
||||
drop_edge_(nullptr)
|
||||
{
|
||||
setScene(&scene_);
|
||||
setDragMode(RubberBandDrag);
|
||||
@@ -231,7 +232,25 @@ void NodeView::keyPressEvent(QKeyEvent *event)
|
||||
void NodeView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (attached_item_) {
|
||||
Node* dropping_node = attached_item_->node();
|
||||
|
||||
DetachItemFromCursor();
|
||||
|
||||
if (drop_edge_) {
|
||||
NodeEdgePtr old_edge = drop_edge_->edge();
|
||||
|
||||
// We have everything we need to place the node in between
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
|
||||
// Remove old edge
|
||||
new NodeEdgeRemoveCommand(old_edge, command);
|
||||
|
||||
// Place new edges
|
||||
new NodeEdgeAddCommand(old_edge->output(), drop_compatible_input_, command);
|
||||
new NodeEdgeAddCommand(dropping_node->output(), old_edge->input(), command);
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
@@ -243,6 +262,57 @@ void NodeView::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
if (attached_item_) {
|
||||
attached_item_->setPos(mapToScene(event->pos()));
|
||||
|
||||
// See if the user clicked on an edge
|
||||
QRect edge_detect_rect(event->pos(), event->pos());
|
||||
|
||||
// FIXME: Hardcoded numbers
|
||||
edge_detect_rect.adjust(-20, -20, 20, 20);
|
||||
|
||||
QList<QGraphicsItem*> items = this->items(edge_detect_rect);
|
||||
|
||||
NodeViewEdge* new_drop_edge = nullptr;
|
||||
|
||||
foreach (QGraphicsItem* item, items) {
|
||||
NodeViewEdge* edge = dynamic_cast<NodeViewEdge*>(item);
|
||||
|
||||
if (edge) {
|
||||
// Try to place this node inside this edge
|
||||
|
||||
// See if the node we're dropping has an input of a compatible data type
|
||||
NodeInput* edges_input = edge->edge()->input();
|
||||
NodeParam::DataType input_type = edges_input->data_type();
|
||||
|
||||
NodeInput* compatible_input = nullptr;
|
||||
|
||||
foreach (NodeParam* drop_node_param, attached_item_->node()->parameters()) {
|
||||
if (drop_node_param->type() == NodeParam::kInput
|
||||
&& static_cast<NodeInput*>(drop_node_param)->data_type() & input_type) {
|
||||
compatible_input = static_cast<NodeInput*>(drop_node_param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (compatible_input) {
|
||||
new_drop_edge = edge;
|
||||
drop_compatible_input_ = compatible_input;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_edge_ != new_drop_edge) {
|
||||
if (drop_edge_) {
|
||||
drop_edge_->SetHighlighted(false);
|
||||
}
|
||||
|
||||
drop_edge_ = new_drop_edge;
|
||||
|
||||
if (drop_edge_) {
|
||||
drop_edge_->SetHighlighted(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ private:
|
||||
|
||||
NodeViewItem* attached_item_;
|
||||
|
||||
NodeViewEdge* drop_edge_;
|
||||
NodeInput* drop_compatible_input_;
|
||||
|
||||
QGraphicsScene scene_;
|
||||
|
||||
QTimer reorganize_timer_;
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
|
||||
QGraphicsLineItem(parent),
|
||||
edge_(nullptr),
|
||||
connected_(false)
|
||||
connected_(false),
|
||||
highlighted_(false)
|
||||
{
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
@@ -101,19 +102,29 @@ void NodeViewEdge::Adjust()
|
||||
void NodeViewEdge::SetConnected(bool c)
|
||||
{
|
||||
connected_ = c;
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetHighlighted(bool e)
|
||||
{
|
||||
highlighted_ = e;
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
QPalette::ColorGroup color_mode;
|
||||
QPalette::ColorGroup color_group = QPalette::Active;
|
||||
QPalette::ColorRole color_role = QPalette::Text;
|
||||
|
||||
if (connected_) {
|
||||
color_mode = QPalette::Active;
|
||||
} else {
|
||||
color_mode = QPalette::Disabled;
|
||||
if (highlighted_) {
|
||||
color_role = QPalette::Highlight;
|
||||
}
|
||||
|
||||
setPen(QPen(widget->palette().color(color_mode, QPalette::Text), edge_width_));
|
||||
if (!connected_) {
|
||||
color_group = QPalette::Disabled;
|
||||
}
|
||||
|
||||
setPen(QPen(widget->palette().color(color_group, color_role), edge_width_));
|
||||
|
||||
QGraphicsLineItem::paint(painter, option, widget);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,13 @@ public:
|
||||
*/
|
||||
void SetConnected(bool c);
|
||||
|
||||
/**
|
||||
* @brief Set highlighted state
|
||||
*
|
||||
* Changes color of edge.
|
||||
*/
|
||||
void SetHighlighted(bool e);
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
|
||||
@@ -77,6 +84,9 @@ private:
|
||||
int edge_width_;
|
||||
|
||||
bool connected_;
|
||||
|
||||
bool highlighted_;
|
||||
|
||||
};
|
||||
|
||||
#endif // NODEEDGEITEM_H
|
||||
|
||||
@@ -45,6 +45,14 @@ NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(NodeOutput *output, NodeInput *inpu
|
||||
{
|
||||
}
|
||||
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(NodeEdgePtr edge, QUndoCommand *parent) :
|
||||
QUndoCommand(parent),
|
||||
output_(edge->output()),
|
||||
input_(edge->input()),
|
||||
done_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeEdgeRemoveCommand::redo()
|
||||
{
|
||||
if (done_) {
|
||||
|
||||
@@ -36,6 +36,7 @@ private:
|
||||
class NodeEdgeRemoveCommand : public QUndoCommand {
|
||||
public:
|
||||
NodeEdgeRemoveCommand(NodeOutput* output, NodeInput* input, QUndoCommand* parent = nullptr);
|
||||
NodeEdgeRemoveCommand(NodeEdgePtr edge, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
Reference in New Issue
Block a user