Skip to content

Commit 5fb96ca

Browse files
authored
Merge pull request #329 from jchanvfx/live_pipe_imporvements
Live pipe improvements.
2 parents 461ceaf + 512a7d2 commit 5fb96ca

File tree

2 files changed

+134
-23
lines changed

2 files changed

+134
-23
lines changed

NodeGraphQt/qgraphics/pipe.py

Lines changed: 109 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -416,12 +416,33 @@ def delete(self):
416416

417417

418418
class LivePipeItem(PipeItem):
419+
"""
420+
Live Pipe item used for drawing the live connection with the cursor.
421+
"""
419422

420423
def __init__(self):
421424
super(LivePipeItem, self).__init__()
422425
self.setZValue(Z_VAL_NODE_WIDGET + 1)
423426
self.shift_selected = False
424427

428+
color = QtGui.QColor(*PipeEnum.ACTIVE_COLOR.value)
429+
pen = QtGui.QPen(color, PipeEnum.WIDTH.value + 0.35)
430+
pen.setJoinStyle(QtCore.Qt.MiterJoin)
431+
pen.setCapStyle(QtCore.Qt.RoundCap)
432+
433+
self._idx_pointer = LivePipePolygonItem(self)
434+
self._idx_pointer.setPolygon(self._arrow)
435+
self._idx_pointer.setBrush(color.darker(300))
436+
self._idx_pointer.setPen(pen)
437+
438+
color = QtGui.QColor(*PipeEnum.ACTIVE_COLOR.value)
439+
color.setAlpha(50)
440+
self._idx_text = QtWidgets.QGraphicsTextItem(self)
441+
self._idx_text.setDefaultTextColor(color)
442+
font = self._idx_text.font()
443+
font.setPointSize(7)
444+
self._idx_text.setFont(font)
445+
425446
def paint(self, painter, option, widget):
426447
"""
427448
Draws the connection line.
@@ -449,21 +470,12 @@ def paint(self, painter, option, widget):
449470
cen_y = self.path().pointAtPercent(0.5).y()
450471
loc_pt = self.path().pointAtPercent(0.9)
451472
tgt_pt = self.path().pointAtPercent(1.0)
452-
start_pt = self.path().pointAtPercent(0.0)
453473

454474
dist = math.hypot(tgt_pt.x() - cen_x, tgt_pt.y() - cen_y)
455475
if dist < 0.05:
456476
painter.restore()
457477
return
458478

459-
# draw start circle
460-
size = 5.0
461-
rect = QtCore.QRectF(start_pt.x() - (size / 2),
462-
start_pt.y() - (size / 2),
463-
size, size)
464-
painter.setBrush(color)
465-
painter.drawEllipse(rect)
466-
467479
# draw middle circle
468480
size = 10.0
469481
if dist < 50.0:
@@ -490,9 +502,92 @@ def paint(self, painter, option, widget):
490502
degrees = math.degrees(radians) + 90
491503
transform.rotate(degrees)
492504

493-
scale = 1.0
494-
if dist < 20.0:
495-
scale = dist / 20.0
496-
transform.scale(scale, scale)
497-
painter.drawPolygon(transform.map(self._arrow))
505+
painter.restore()
506+
507+
def draw_path(self, start_port, end_port=None, cursor_pos=None,
508+
color_mode=None):
509+
"""
510+
re-implemented to also update the index pointer arrow position.
511+
512+
Args:
513+
start_port (PortItem): port used to draw the starting point.
514+
end_port (PortItem): port used to draw the end point.
515+
cursor_pos (QtCore.QPointF): cursor position if specified this
516+
will be the draw end point.
517+
color_mode (str): arrow index pointer color mode
518+
('accept', 'reject' or None).
519+
"""
520+
super(LivePipeItem, self).draw_path(start_port, end_port, cursor_pos)
521+
self.draw_index_pointer(start_port, cursor_pos, color_mode)
522+
523+
def draw_index_pointer(self, start_port, cursor_pos, color_mode=None):
524+
"""
525+
Update the index pointer arrow position and direction when the
526+
live pipe path is redrawn.
527+
528+
Args:
529+
start_port (PortItem): start port item.
530+
cursor_pos (QtCore.QPoint): cursor scene position.
531+
color_mode (str): arrow index pointer color mode
532+
('accept', 'reject' or None).
533+
"""
534+
text_rect = self._idx_text.boundingRect()
535+
536+
transform = QtGui.QTransform()
537+
transform.translate(cursor_pos.x(), cursor_pos.y())
538+
if self.viewer_layout_direction() is LayoutDirectionEnum.VERTICAL.value:
539+
text_pos = (
540+
cursor_pos.x() + (text_rect.width() / 2.5),
541+
cursor_pos.y() - (text_rect.height() / 2)
542+
)
543+
if start_port.port_type == PortTypeEnum.OUT.value:
544+
transform.rotate(180)
545+
elif self.viewer_layout_direction() is LayoutDirectionEnum.HORIZONTAL.value:
546+
text_pos = (
547+
cursor_pos.x() - (text_rect.width() / 2),
548+
cursor_pos.y() - (text_rect.height() * 1.25)
549+
)
550+
if start_port.port_type == PortTypeEnum.IN.value:
551+
transform.rotate(-90)
552+
else:
553+
transform.rotate(90)
554+
self._idx_text.setPos(*text_pos)
555+
self._idx_text.setPlainText('{}'.format(start_port.name))
556+
557+
self._idx_pointer.setPolygon(transform.map(self._arrow))
558+
559+
if color_mode == 'accept':
560+
color = QtGui.QColor(*PipeEnum.HIGHLIGHT_COLOR.value)
561+
elif color_mode == 'reject':
562+
color = QtGui.QColor(*PipeEnum.DISABLED_COLOR.value)
563+
else:
564+
color = QtGui.QColor(*PipeEnum.ACTIVE_COLOR.value)
565+
566+
pen = self._idx_pointer.pen()
567+
pen.setColor(color)
568+
self._idx_pointer.setBrush(color.darker(300))
569+
self._idx_pointer.setPen(pen)
570+
571+
572+
class LivePipePolygonItem(QtWidgets.QGraphicsPolygonItem):
573+
"""
574+
Custom live pipe polygon shape.
575+
"""
576+
577+
def __init__(self, parent):
578+
super(LivePipePolygonItem, self).__init__(parent)
579+
self.setFlag(self.ItemIsSelectable, True)
580+
581+
def paint(self, painter, option, widget):
582+
"""
583+
Args:
584+
painter (QtGui.QPainter): painter used for drawing the item.
585+
option (QtGui.QStyleOptionGraphicsItem):
586+
used to describe the parameters needed to draw.
587+
widget (QtWidgets.QWidget): not used.
588+
"""
589+
painter.save()
590+
painter.setBrush(self.brush())
591+
painter.setPen(self.pen())
592+
painter.drawPolygon(self.polygon())
498593
painter.restore()

NodeGraphQt/widgets/viewer.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ def keyReleaseEvent(self, event):
637637
def sceneMouseMoveEvent(self, event):
638638
"""
639639
triggered mouse move event for the scene.
640-
- redraw the connection pipe.
640+
- redraw the live connection pipe.
641641
642642
Args:
643643
event (QtWidgets.QGraphicsSceneMouseEvent):
@@ -649,15 +649,27 @@ def sceneMouseMoveEvent(self, event):
649649
return
650650

651651
pos = event.scenePos()
652-
items = self.scene().items(pos)
653-
if items and isinstance(items[0], PortItem):
654-
x = items[0].boundingRect().width() / 2
655-
y = items[0].boundingRect().height() / 2
656-
pos = items[0].scenePos()
657-
pos.setX(pos.x() + x)
658-
pos.setY(pos.y() + y)
652+
color_mode = None
653+
for item in self.scene().items(pos):
654+
if isinstance(item, PortItem):
655+
x = item.boundingRect().width() / 2
656+
y = item.boundingRect().height() / 2
657+
pos = item.scenePos()
658+
pos.setX(pos.x() + x)
659+
pos.setY(pos.y() + y)
660+
if item == self._start_port:
661+
break
662+
color_mode = 'accept'
663+
if self.acyclic:
664+
if item.node == self._start_port.node:
665+
color_mode = 'reject'
666+
elif item.port_type == self._start_port.port_type:
667+
color_mode = 'reject'
668+
break
659669

660-
self._LIVE_PIPE.draw_path(self._start_port, cursor_pos=pos)
670+
self._LIVE_PIPE.draw_path(
671+
self._start_port, cursor_pos=pos, color_mode=color_mode
672+
)
661673

662674
def sceneMousePressEvent(self, event):
663675
"""
@@ -874,6 +886,10 @@ def start_live_connection(self, selected_port):
874886
elif self._start_port == PortTypeEnum.OUT.value:
875887
self._LIVE_PIPE.output_port = self._start_port
876888
self._LIVE_PIPE.setVisible(True)
889+
self._LIVE_PIPE.draw_index_pointer(
890+
selected_port,
891+
self.mapToScene(self._origin_pos)
892+
)
877893

878894
def end_live_connection(self):
879895
"""

0 commit comments

Comments
 (0)