-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode_edge_intersect.py
More file actions
144 lines (117 loc) · 5.08 KB
/
Copy pathnode_edge_intersect.py
File metadata and controls
144 lines (117 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- coding: utf-8 -*-
"""
A module containing the intersecting nodes functionality. If a node gets dragged and dropped on an existing edge
it will intersect that edge.
"""
from qtpy.QtWidgets import QGraphicsView
from qtpy.QtCore import QRectF
from nodeeditor.node_edge import Edge
class EdgeIntersect:
def __init__(self, grView: "QGraphicsView"):
self.grScene = grView.grScene
self.grView = grView
self.draggedNode = None
self.hoveredList = []
def enterState(self, node: "Node"):
"""
Initialize when we enter the state
:param node: :class:`~nodeeditor.node_node.Node` which we started to drag
:type node: :class:`~nodeeditor.node_node.Node`
"""
self.hoveredList = []
self.draggedNode = node
def leaveState(self, scene_pos_x: float, scene_pos_y: float):
"""
Deinit when we leave this state
:param scene_pos_x: scene position x
:type scene_pos_x: `float`
:param scene_pos_y: scene position y
:type scene_pos_y: `float`
"""
self.dropNode(self.draggedNode, scene_pos_x, scene_pos_y)
self.draggedNode = None
self.hoveredList = []
def dropNode(self, node: "Node", scene_pos_x: float, scene_pos_y: float):
"""
Code handling the dropping of a node on an existing edge.
:param scene_pos_x: scene position x
:type scene_pos_x: `float`
:param scene_pos_y: scene position y
:type scene_pos_y: `float`
"""
node_box = self.hotZoneRect(node)
# check if the node is dropped on an existing edge
edge = self.intersect(node_box)
if edge is None: return
if self.isConnected(node): return
# determine the order of start and end
if edge.start_socket.is_output:
socket_start = edge.start_socket
socket_end = edge.end_socket
else:
socket_start = edge.end_socket
socket_end = edge.start_socket
# The new edges will have the same edge_type as the intersected edge
edge_type = edge.edge_type
edge.remove()
self.grView.grScene.scene.history.storeHistory('Delete existing edge', setModified=True)
new_node_socket_in = node.inputs[0]
Edge(self.grScene.scene, socket_start, new_node_socket_in, edge_type=edge_type)
new_node_socket_out = node.outputs[0]
Edge(self.grScene.scene, new_node_socket_out, socket_end, edge_type=edge_type)
self.grView.grScene.scene.history.storeHistory('Created new edges by dropping node', setModified=True)
def hotZoneRect(self, node: 'Node') -> 'QRectF':
"""
Returns A QRectF of creating a box around a node
:param node: :class:`~nodeeditor.node_node.Node` for which we want to get `QRectF` describing its position and area
:type node: :class:`~nodeeditor.node_node.Node`
:return: `QRectF` describing node's position and area
:rtype: `QRectF`
"""
nodePos = node.grNode.scenePos()
x = nodePos.x()
y = nodePos.y()
w = node.grNode.width
h = node.grNode.height
return QRectF(x, y, w, h)
def update(self, scene_pos_x: float, scene_pos_y: float):
"""
Updating during mouse move when grView is in this state
:param scene_pos_x: scene position x
:type scene_pos_x: `float`
:param scene_pos_y: scene position y
:type scene_pos_y: `float`
"""
rect = self.hotZoneRect(self.draggedNode)
grItems = self.grScene.items(rect)
for grEdge in self.hoveredList: grEdge.hovered = False
self.hoveredList = []
for grItem in grItems:
if hasattr(grItem, 'edge') and not self.draggedNode.hasConnectedEdge(grItem.edge):
self.hoveredList.append(grItem)
grItem.hovered = True
def intersect(self, node_box: 'QRectF') -> 'Edge':
"""
Checking for intersection of a rectangle (usually a `Node`) with edges in the scene
:param node_box: `QRectF` for which we want find intersecting `Edges`
:type node_box: `QRectF`
:return: :class:`~nodeeditor.node_edge.Edge` or `None` if the node is being cut by an `Edge`
:rtype: :class:`~nodeeditor.node_edge.Edge`
"""
# returns the first edge that intersects with the dropped node, ignores the rest
grItems = self.grScene.items(node_box)
for grItem in grItems:
if hasattr(grItem, 'edge') and not self.draggedNode.hasConnectedEdge(grItem.edge):
return grItem.edge
return None
def isConnected(self, node: 'Node'):
"""
Return ``True`` if node got any connections
:param node: :class:`~nodeeditor.node_node.Node` which connections to check
:type node: :class:`~nodeeditor.node_node.Node`
:return:
"""
# Nodes with only inputs or outputs are excluded
if node.inputs == [] or node.outputs == []: return True
# Check if the node has edges connected
return node.getInput() or node.getOutputs()