Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection path for nodes connected to "upstream" nodes #394

Open
xraybrian opened this issue Oct 25, 2023 · 4 comments
Open

Connection path for nodes connected to "upstream" nodes #394

xraybrian opened this issue Oct 25, 2023 · 4 comments

Comments

@xraybrian
Copy link

We have very large nodegraphs with multiple connections from outputs to inputs that are "upstream". For angled pipes, this results in pipes that run diagonal rather than right angles and makes viewing the graph confusing.

Would it be possible to update the pipe pathing (specifically for angled pipes) so that the pipes only make 90 degree bends? I believe this requires the addition of two more vertices for the pipes.

@jchanvfx
Copy link
Owner

Hi @xraybrian

Do you have like an example screenshot of what you're after? I probably won't be able to add this feature anytime soon but it'll be good to have it here for future reference.

If you want to have a go at making some tweaks here's some starting points for where the pipes are drawn 😃
https://github.com/jchanvfx/NodeGraphQt/blob/main/NodeGraphQt/qgraphics/pipe.py#L334
https://github.com/jchanvfx/NodeGraphQt/blob/main/NodeGraphQt/qgraphics/pipe.py#L247
https://github.com/jchanvfx/NodeGraphQt/blob/main/NodeGraphQt/qgraphics/pipe.py#L247

@xraybrian
Copy link
Author

xraybrian commented Feb 14, 2024 via email

@xraybrian
Copy link
Author

xraybrian commented Feb 14, 2024 via email

@xraybrian
Copy link
Author

Here is my suggested code for _draw_path_horizontal and _draw_path_vertical:

def _draw_path_vertical(self, start_port, pos1, pos2, path,
offset = 30):
"""
Draws the vertical path between ports.

    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.
        
        offset (float): the offset to apply for the more complex circuit

    """
    if self.viewer_pipe_layout() == PipeLayoutEnum.CURVED.value:
        ctr_offset_y1, ctr_offset_y2 = pos1.y(), pos2.y()
        tangent = abs(ctr_offset_y1 - ctr_offset_y2)

        max_height = start_port.node.boundingRect().height()
        tangent = min(tangent, max_height)
        if start_port.port_type == PortTypeEnum.IN.value:
            ctr_offset_y1 -= tangent
            ctr_offset_y2 += tangent
        else:
            ctr_offset_y1 += tangent
            ctr_offset_y2 -= tangent

        ctr_point1 = QtCore.QPointF(pos1.x(), ctr_offset_y1)
        ctr_point2 = QtCore.QPointF(pos2.x(), ctr_offset_y2)
        path.cubicTo(ctr_point1, ctr_point2, pos2)
        self.setPath(path)
    elif self.viewer_pipe_layout() == PipeLayoutEnum.ANGLE.value:          

        # start at p1
        path.lineTo(pos1)

        # there are two cases, one where an output is connected
        # to an input, but the input is "behind" the output, i.e.
        # the x-value of the input is smaller than the output port
        
        # the other case is simpler, where the output port x value is 
        # smaller than the input port
        
        # first calculate the simple x-distance
        simple_distance_y = pos2.y() - pos1.y()
        mid_point_x = (pos1.x() + pos2.x()) / 2
        mid_point_y = (pos1.y() + pos2.y()) / 2

        
        if ((simple_distance_y > 0 and start_port.port_type == PortTypeEnum.OUT.value) or
            (simple_distance_y < 0 and start_port.port_type == PortTypeEnum.IN.value)):
                
            # this is the simplest case
            path.lineTo(QtCore.QPointF(pos1.x(), mid_point_y))
            path.lineTo(QtCore.QPointF(pos2.x(), mid_point_y))
            path.lineTo(QtCore.QPointF(pos2))
                
        else:
            
            # we need a slightly more complex circuit but not too bad
            path.lineTo(QtCore.QPointF(pos1.x(), pos1.y() - offset))
            path.lineTo(QtCore.QPointF(mid_point_x, pos1.y() - offset))
            path.lineTo(QtCore.QPointF(mid_point_x, pos2.y() + offset))
            path.lineTo(QtCore.QPointF(pos2.x(), pos2.y() + offset, ))
                

        # end at p2
        path.lineTo(QtCore.QPointF(pos2))

        self.setPath(path)

def _draw_path_horizontal(self, start_port, pos1, pos2, path,
                          offset = 30):
    """
    Draws the horizontal path between ports.

    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.
        
        offset (float): the offset to apply for the more complex circuit
    """
    if self.viewer_pipe_layout() == PipeLayoutEnum.CURVED.value:
        ctr_offset_x1, ctr_offset_x2 = pos1.x(), pos2.x()
        tangent = abs(ctr_offset_x1 - ctr_offset_x2)

        max_width = start_port.node.boundingRect().width()
        tangent = min(tangent, max_width)
        if start_port.port_type == PortTypeEnum.IN.value:
            ctr_offset_x1 -= tangent
            ctr_offset_x2 += tangent
        else:
            ctr_offset_x1 += tangent
            ctr_offset_x2 -= tangent

        ctr_point1 = QtCore.QPointF(ctr_offset_x1, pos1.y())
        ctr_point2 = QtCore.QPointF(ctr_offset_x2, pos2.y())
        path.cubicTo(ctr_point1, ctr_point2, pos2)
        self.setPath(path)
    elif self.viewer_pipe_layout() == PipeLayoutEnum.ANGLE.value:

        # start at p1
        path.lineTo(pos1)

        # there are two cases, one where an output is connected
        # to an input, but the input is "behind" the output, i.e.
        # the x-value of the input is smaller than the output port
        
        # the other case is simpler, where the output port x value is 
        # smaller than the input port
        
        # first calculate the simple x-distance
        simple_distance_x = pos2.x() - pos1.x()
        mid_point_x = (pos1.x() + pos2.x()) / 2
        mid_point_y = (pos1.y() + pos2.y()) / 2

        
        if ((simple_distance_x > 0 and start_port.port_type == PortTypeEnum.OUT.value) or
            (simple_distance_x < 0 and start_port.port_type == PortTypeEnum.IN.value)):
                
            # this is the simplest case
            path.lineTo(QtCore.QPointF(mid_point_x , pos1.y()))
            path.lineTo(QtCore.QPointF(mid_point_x , pos2.y()))
            path.lineTo(QtCore.QPointF(pos2))
                
        else:
            
            # we need a slightly more complex circuit but not too bad
            path.lineTo(QtCore.QPointF(pos1.x() - offset, pos1.y()))
            path.lineTo(QtCore.QPointF(pos1.x() - offset, mid_point_y))
            path.lineTo(QtCore.QPointF(pos2.x() + offset, mid_point_y))
            path.lineTo(QtCore.QPointF(pos2.x() + offset, pos2.y()))
                

        # end at p2
        path.lineTo(QtCore.QPointF(pos2))

        self.setPath(path)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants