From 1896ebd473b1a0d4a91794cce9d73694c61d8f81 Mon Sep 17 00:00:00 2001 From: jchanvfx Date: Sat, 6 May 2023 16:05:16 +1200 Subject: [PATCH 1/4] horizontal cyclic node connection pipe drawing. --- NodeGraphQt/qgraphics/pipe.py | 89 +++++++++++++++++++++++++++++++---- NodeGraphQt/widgets/viewer.py | 8 +++- 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/NodeGraphQt/qgraphics/pipe.py b/NodeGraphQt/qgraphics/pipe.py index bd3cf827..415be7a0 100644 --- a/NodeGraphQt/qgraphics/pipe.py +++ b/NodeGraphQt/qgraphics/pipe.py @@ -158,6 +158,46 @@ def paint(self, painter, option, widget): # QPaintDevice: Cannot destroy paint device that is being painted. painter.restore() + def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path): + """ + Draws the pipe path around the node if the in port and out port + connect to each other for cycle connection. + + Args: + start_port (PortItem): port used to draw the starting point. + pos1 (QPointF): start port position. + pos2 (QPointF): end port position. + path (QPainterPath): path to draw. + """ + + def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path): + """ + Draws the pipe path around the node if the in port and out port + connect to each other for cycle connection. + + Args: + start_port (PortItem): port used to draw the starting point. + pos1 (QPointF): start port position. + pos2 (QPointF): end port position. + path (QPainterPath): path to draw. + """ + ptype = start_port.port_type + in_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 + out_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 + + n_rect = start_port.node.boundingRect() + padding = 40 + + left = out_pos.x() + padding + right = in_pos.x() - padding + path.moveTo(out_pos) + path.lineTo(left, out_pos.y()) + path.lineTo(left, out_pos.y() + n_rect.bottom()) + path.lineTo(right, out_pos.y() + n_rect.bottom()) + path.lineTo(right, in_pos.y()) + path.lineTo(in_pos) + self.setPath(path) + def __draw_path_vertical(self, start_port, pos1, pos2, path): """ Draws the vertical path between ports. @@ -274,14 +314,29 @@ def draw_path(self, start_port, end_port=None, cursor_pos=None): path = QtGui.QPainterPath() path.moveTo(line.x1(), line.y1()) + direction = self.viewer_layout_direction() + + if end_port and not self.viewer().acyclic: + if end_port.node == start_port.node: + if direction is LayoutDirectionEnum.VERTICAL.value: + self.__draw_path_cycled_vertical( + start_port, pos1, pos2, path + ) + return + elif direction is LayoutDirectionEnum.HORIZONTAL.value: + self.__draw_path_cycled_horizontal( + start_port, pos1, pos2, path + ) + return + if self.viewer_pipe_layout() == PipeLayoutEnum.STRAIGHT.value: path.lineTo(pos2) self.setPath(path) return - if self.viewer_layout_direction() is LayoutDirectionEnum.VERTICAL.value: + if direction is LayoutDirectionEnum.VERTICAL.value: self.__draw_path_vertical(start_port, pos1, pos2, path) - elif self.viewer_layout_direction() is LayoutDirectionEnum.HORIZONTAL.value: + elif direction is LayoutDirectionEnum.HORIZONTAL.value: self.__draw_path_horizontal(start_port, pos1, pos2, path) def reset_path(self): @@ -289,7 +344,7 @@ def reset_path(self): self.setPath(path) @staticmethod - def calc_distance(p1, p2): + def _calc_distance(p1, p2): x = math.pow((p2.x() - p1.x()), 2) y = math.pow((p2.y() - p1.y()), 2) return math.sqrt(x + y) @@ -297,22 +352,38 @@ def calc_distance(p1, p2): def port_from_pos(self, pos, reverse=False): inport_pos = self.input_port.scenePos() outport_pos = self.output_port.scenePos() - input_dist = self.calc_distance(inport_pos, pos) - output_dist = self.calc_distance(outport_pos, pos) + input_dist = self._calc_distance(inport_pos, pos) + output_dist = self._calc_distance(outport_pos, pos) if input_dist < output_dist: port = self.output_port if reverse else self.input_port else: port = self.input_port if reverse else self.output_port return port - def viewer_pipe_layout(self): + def viewer(self): + """ + Returns: + NodeViewer: node graph viewer. + """ if self.scene(): - viewer = self.scene().viewer() + return self.scene().viewer() + + def viewer_pipe_layout(self): + """ + Returns: + int: pipe layout mode. + """ + viewer = self.viewer() + if viewer: return viewer.get_pipe_layout() def viewer_layout_direction(self): - if self.scene(): - viewer = self.scene().viewer() + """ + Returns: + int: graph layout mode. + """ + viewer = self.viewer() + if viewer: return viewer.get_layout_direction() def activate(self): diff --git a/NodeGraphQt/widgets/viewer.py b/NodeGraphQt/widgets/viewer.py index 2bde3770..cf439544 100644 --- a/NodeGraphQt/widgets/viewer.py +++ b/NodeGraphQt/widgets/viewer.py @@ -897,6 +897,12 @@ def apply_live_connection(self, event): if self._start_port is end_port: return + # if connection to itself + same_node_connection = end_port.node == self._start_port.node + if not self.acyclic: + # allow a node cycle connection. + same_node_connection = False + # restore connection check. restore_connection = any([ # if the end port is locked. @@ -904,7 +910,7 @@ def apply_live_connection(self, event): # if same port type. end_port.port_type == self._start_port.port_type, # if connection to itself. - end_port.node == self._start_port.node, + same_node_connection, # if end port is the start port. end_port == self._start_port, # if detached port is the end port. From aefbc4000e00afadf2792f7c7e704a7d819ef776 Mon Sep 17 00:00:00 2001 From: jchanvfx Date: Sat, 6 May 2023 17:17:25 +1200 Subject: [PATCH 2/4] vertical cyclic node connection pipe drawing. --- NodeGraphQt/qgraphics/pipe.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/NodeGraphQt/qgraphics/pipe.py b/NodeGraphQt/qgraphics/pipe.py index 415be7a0..39810366 100644 --- a/NodeGraphQt/qgraphics/pipe.py +++ b/NodeGraphQt/qgraphics/pipe.py @@ -160,8 +160,7 @@ def paint(self, painter, option, widget): def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path): """ - Draws the pipe path around the node if the in port and out port - connect to each other for cycle connection. + Draw pipe vertically around node if connection is cyclic. Args: start_port (PortItem): port used to draw the starting point. @@ -169,11 +168,26 @@ def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path): pos2 (QPointF): end port position. path (QPainterPath): path to draw. """ + ptype = start_port.port_type + in_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 + out_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 + + n_rect = start_port.node.boundingRect() + padding = 40 + + top = in_pos.y() - padding + bottom = out_pos.y() + padding + path.moveTo(out_pos) + path.lineTo(out_pos.x(), bottom) + path.lineTo(out_pos.x() + n_rect.right(), bottom) + path.lineTo(out_pos.x() + n_rect.right(), top) + path.lineTo(in_pos.x(), top) + path.lineTo(in_pos) + self.setPath(path) def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path): """ - Draws the pipe path around the node if the in port and out port - connect to each other for cycle connection. + Draw pipe horizontally around node if connection is cyclic. Args: start_port (PortItem): port used to draw the starting point. From e25537a52559288e8fb2112242f43f82eebc3067 Mon Sep 17 00:00:00 2001 From: jchanvfx Date: Sat, 6 May 2023 17:20:14 +1200 Subject: [PATCH 3/4] version bump. --- NodeGraphQt/pkg_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeGraphQt/pkg_info.py b/NodeGraphQt/pkg_info.py index 2f4f6897..56d18635 100644 --- a/NodeGraphQt/pkg_info.py +++ b/NodeGraphQt/pkg_info.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -__version__ = '0.5.9' +__version__ = '0.5.10' __status__ = 'Work in Progress' __license__ = 'MIT' From 42564d7c2ac1131ac1c91df988bfb2b4df408481 Mon Sep 17 00:00:00 2001 From: jchanvfx Date: Sun, 7 May 2023 01:00:43 +1200 Subject: [PATCH 4/4] draw direction fix. --- NodeGraphQt/qgraphics/pipe.py | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/NodeGraphQt/qgraphics/pipe.py b/NodeGraphQt/qgraphics/pipe.py index 39810366..684a1f39 100644 --- a/NodeGraphQt/qgraphics/pipe.py +++ b/NodeGraphQt/qgraphics/pipe.py @@ -168,21 +168,20 @@ def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path): pos2 (QPointF): end port position. path (QPainterPath): path to draw. """ + n_rect = start_port.node.boundingRect() ptype = start_port.port_type - in_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 - out_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 + start_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 + end_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 - n_rect = start_port.node.boundingRect() padding = 40 - - top = in_pos.y() - padding - bottom = out_pos.y() + padding - path.moveTo(out_pos) - path.lineTo(out_pos.x(), bottom) - path.lineTo(out_pos.x() + n_rect.right(), bottom) - path.lineTo(out_pos.x() + n_rect.right(), top) - path.lineTo(in_pos.x(), top) - path.lineTo(in_pos) + top = start_pos.y() - padding + bottom = end_pos.y() + padding + path.moveTo(end_pos) + path.lineTo(end_pos.x(), bottom) + path.lineTo(end_pos.x() + n_rect.right(), bottom) + path.lineTo(end_pos.x() + n_rect.right(), top) + path.lineTo(start_pos.x(), top) + path.lineTo(start_pos) self.setPath(path) def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path): @@ -195,21 +194,20 @@ def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path): pos2 (QPointF): end port position. path (QPainterPath): path to draw. """ + n_rect = start_port.node.boundingRect() ptype = start_port.port_type - in_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 - out_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 + start_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2 + end_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1 - n_rect = start_port.node.boundingRect() padding = 40 - - left = out_pos.x() + padding - right = in_pos.x() - padding - path.moveTo(out_pos) - path.lineTo(left, out_pos.y()) - path.lineTo(left, out_pos.y() + n_rect.bottom()) - path.lineTo(right, out_pos.y() + n_rect.bottom()) - path.lineTo(right, in_pos.y()) - path.lineTo(in_pos) + left = end_pos.x() + padding + right = start_pos.x() - padding + path.moveTo(start_pos) + path.lineTo(right, start_pos.y()) + path.lineTo(right, end_pos.y() + n_rect.bottom()) + path.lineTo(left, end_pos.y() + n_rect.bottom()) + path.lineTo(left, end_pos.y()) + path.lineTo(end_pos) self.setPath(path) def __draw_path_vertical(self, start_port, pos1, pos2, path): @@ -326,7 +324,6 @@ def draw_path(self, start_port, end_port=None, cursor_pos=None): line = QtCore.QLineF(pos1, pos2) path = QtGui.QPainterPath() - path.moveTo(line.x1(), line.y1()) direction = self.viewer_layout_direction() @@ -343,6 +340,8 @@ def draw_path(self, start_port, end_port=None, cursor_pos=None): ) return + path.moveTo(line.x1(), line.y1()) + if self.viewer_pipe_layout() == PipeLayoutEnum.STRAIGHT.value: path.lineTo(pos2) self.setPath(path)