-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode_socket.py
More file actions
206 lines (171 loc) · 8.03 KB
/
Copy pathnode_socket.py
File metadata and controls
206 lines (171 loc) · 8.03 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# -*- coding: utf-8 -*-
"""
A module containing NodeEditor's class for representing Socket and Socket Position Constants.
"""
from collections import OrderedDict
from nodeeditor.node_serializable import Serializable
from nodeeditor.node_graphics_socket import QDMGraphicsSocket
LEFT_TOP = 1 #:
LEFT_CENTER =2 #:
LEFT_BOTTOM = 3 #:
RIGHT_TOP = 4 #:
RIGHT_CENTER = 5 #:
RIGHT_BOTTOM = 6 #:
DEBUG = False
DEBUG_REMOVE_WARNINGS = False
class Socket(Serializable):
Socket_GR_Class = QDMGraphicsSocket
"""Class representing Socket."""
def __init__(self, node: 'Node', index: int=0, position: int=LEFT_TOP, socket_type: int=1, multi_edges: bool=True,
count_on_this_node_side: int=1, is_input: bool=False, label: str=""):
"""
:param node: reference to the :class:`~nodeeditor.node_node.Node` containing this `Socket`
:type node: :class:`~nodeeditor.node_node.Node`
:param index: Current index of this socket in the position
:type index: ``int``
:param position: Socket position. See :ref:`socket-position-constants`
:param socket_type: Constant defining type(color) of this socket
:param multi_edges: Can this socket have multiple `Edges` connected?
:type multi_edges: ``bool``
:param count_on_this_node_side: number of total sockets on this position
:type count_on_this_node_side: ``int``
:param is_input: Is this an input `Socket`?
:type is_input: ``bool``
:param label: Label text to display next to the socket
:type label: ``str``
:Instance Attributes:
- **node** - reference to the :class:`~nodeeditor.node_node.Node` containing this `Socket`
- **edges** - list of `Edges` connected to this `Socket`
- **grSocket** - reference to the :class:`~nodeeditor.node_graphics_socket.QDMGraphicsSocket`
- **position** - Socket position. See :ref:`socket-position-constants`
- **index** - Current index of this socket in the position
- **socket_type** - Constant defining type(color) of this socket
- **count_on_this_node_side** - number of sockets on this position
- **is_multi_edges** - ``True`` if `Socket` can contain multiple `Edges`
- **is_input** - ``True`` if this socket serves for Input
- **is_output** - ``True`` if this socket serves for Output
- **label** - Label text displayed next to the socket
"""
super().__init__()
self.node = node
self.position = position
self.index = index
self.socket_type = socket_type
self.count_on_this_node_side = count_on_this_node_side
self.is_multi_edges = multi_edges
self.is_input = is_input
self.is_output = not self.is_input
self.label = label
if DEBUG: print("Socket -- creating with", self.index, self.position, "for nodeeditor", self.node)
self.grSocket = self.__class__.Socket_GR_Class(self)
self.setSocketPosition()
self.edges = []
def __str__(self):
return "<Socket #%d %s %s..%s>" % (
self.index, "ME" if self.is_multi_edges else "SE", hex(id(self))[2:5], hex(id(self))[-3:]
)
def delete(self):
"""Delete this `Socket` from graphics scene for sure"""
self.grSocket.setParentItem(None)
self.node.scene.grScene.removeItem(self.grSocket)
del self.grSocket
def changeSocketType(self, new_socket_type: int) -> bool:
"""
Change the Socket Type
:param new_socket_type: new socket type
:type new_socket_type: ``int``
:return: Returns ``True`` if the socket type was actually changed
:rtype: ``bool``
"""
if self.socket_type != new_socket_type:
self.socket_type = new_socket_type
self.grSocket.changeSocketType()
return True
return False
def setSocketPosition(self):
"""Helper function to set `Graphics Socket` position. Exact socket position is calculated
inside :class:`~nodeeditor.node_node.Node`."""
self.grSocket.setPos(*self.node.getSocketPosition(self.index, self.position, self.count_on_this_node_side))
def getSocketPosition(self):
"""
:return: Returns this `Socket` position according to the implementation stored in
:class:`~nodeeditor.node_node.Node`
:rtype: ``x, y`` position
"""
if DEBUG: print(" GSP: ", self.index, self.position, "nodeeditor:", self.node)
res = self.node.getSocketPosition(self.index, self.position, self.count_on_this_node_side)
if DEBUG: print(" res", res)
return res
def hasAnyEdge(self) -> bool:
"""
Returns ``True`` if any :class:`~nodeeditor.node_edge.Edge` is connected to this socket
:return: ``True`` if any :class:`~nodeeditor.node_edge.Edge` is connected to this socket
:rtype: ``bool``
"""
return len(self.edges) > 0
def isConnected(self, edge: 'Edge') -> bool:
"""
Returns ``True`` if :class:`~nodeeditor.node_edge.Edge` is connected to this `Socket`
:param edge: :class:`~nodeeditor.node_edge.Edge` to check if it is connected to this `Socket`
:type edge: :class:`~nodeeditor.node_edge.Edge`
:return: ``True`` if `Edge` is connected to this socket
:rtype: ``bool``
"""
return edge in self.edges
def addEdge(self, edge: 'Edge'):
"""
Append an Edge to the list of connected Edges
:param edge: :class:`~nodeeditor.node_edge.Edge` to connect to this `Socket`
:type edge: :class:`~nodeeditor.node_edge.Edge`
"""
self.edges.append(edge)
def removeEdge(self, edge: 'Edge'):
"""
Disconnect passed :class:`~nodeeditor.node_edge.Edge` from this `Socket`
:param edge: :class:`~nodeeditor.node_edge.Edge` to disconnect
:type edge: :class:`~nodeeditor.node_edge.Edge`
"""
if edge in self.edges: self.edges.remove(edge)
else:
if DEBUG_REMOVE_WARNINGS:
print("!W:", "Socket::removeEdge", "wanna remove edge", edge,
"from self.edges but it's not in the list!")
def removeAllEdges(self, silent: bool=False):
"""Disconnect all `Edges` from this `Socket`"""
while self.edges:
edge = self.edges.pop(0)
if silent:
edge.remove(silent_for_socket=self)
else:
edge.remove() # just remove all with notifications
def determineMultiEdges(self, data: dict) -> bool:
"""
Deserialization helper function. In our tutorials we created a new version of graph data format.
This function is here to help solve the issue of opening older files in the newer format.
If the 'multi_edges' param is missing in the dictionary, we determine if this `Socket`
should support multiple `Edges`.
:param data: `Socket` data in ``dict`` format for deserialization
:type data: ``dict``
:return: ``True`` if this `Socket` should support multi_edges
"""
if 'multi_edges' in data:
return data['multi_edges']
else:
# probably older version of file, make RIGHT socket multiedged by default
return data['position'] in (RIGHT_BOTTOM, RIGHT_TOP)
def serialize(self) -> OrderedDict:
return OrderedDict([
('id', self.id),
('index', self.index),
('multi_edges', self.is_multi_edges),
('position', self.position),
('socket_type', self.socket_type),
('label', self.label),
])
def deserialize(self, data: dict, hashmap: dict={}, restore_id: bool=True) -> bool:
if restore_id: self.id = data['id']
self.is_multi_edges = self.determineMultiEdges(data)
self.changeSocketType(data['socket_type'])
self.label = data.get('label', '') # Handle backward compatibility
hashmap[data['id']] = self
return True