-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode_graphics_socket.py
More file actions
177 lines (150 loc) · 6.67 KB
/
Copy pathnode_graphics_socket.py
File metadata and controls
177 lines (150 loc) · 6.67 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
# -*- coding: utf-8 -*-
"""
A module containing Graphics representation of a :class:`~nodeeditor.node_socket.Socket`
"""
from qtpy.QtWidgets import QGraphicsItem
from qtpy.QtGui import QColor, QBrush, QPen, QFont, QFontMetrics
from qtpy.QtCore import Qt, QRectF
SOCKET_COLORS = [
QColor("#FFFF7700"),
QColor("#FF52e220"),
QColor("#FF0056a6"),
QColor("#FFa86db1"),
QColor("#FFb54747"),
QColor("#FFdbe220"),
QColor("#FF888888"),
QColor("#FFFF7700"),
QColor("#FF52e220"),
QColor("#FF0056a6"),
QColor("#FFa86db1"),
QColor("#FFb54747"),
QColor("#FFdbe220"),
QColor("#FF888888"),
]
class QDMGraphicsSocket(QGraphicsItem):
"""Class representing Graphic `Socket` in ``QGraphicsScene``"""
def __init__(self, socket:'Socket'):
"""
:param socket: reference to :class:`~nodeeditor.node_socket.Socket`
:type socket: :class:`~nodeeditor.node_socket.Socket`
"""
super().__init__(socket.node.grNode)
self.socket = socket
self.isHighlighted = False
self.radius = 6
self.outline_width = 1
self.label_font = QFont("Arial", 8)
self.label_color = QColor("#FFFFFF")
self.label_margin = 8 # Distance between socket and label
self.initAssets()
@property
def socket_type(self):
return self.socket.socket_type
def getSocketColor(self, key):
"""Returns the ``QColor`` for this ``key``"""
if type(key) == int: return SOCKET_COLORS[key]
elif type(key) == str: return QColor(key)
return Qt.transparent
def changeSocketType(self):
"""Change the Socket Type"""
self._color_background = self.getSocketColor(self.socket_type)
self._brush = QBrush(self._color_background)
# print("Socket changed to:", self._color_background.getRgbF())
self.update()
def initAssets(self):
"""Initialize ``QObjects`` like ``QColor``, ``QPen`` and ``QBrush``"""
# determine socket color
self._color_background = self.getSocketColor(self.socket_type)
self._color_outline = QColor("#FF000000")
self._color_highlight = QColor("#FF37A6FF")
self._pen = QPen(self._color_outline)
self._pen.setWidthF(self.outline_width)
self._pen_highlight = QPen(self._color_highlight)
self._pen_highlight.setWidthF(2.0)
self._brush = QBrush(self._color_background)
def getLOD(self):
"""Get Level of Detail based on current zoom level"""
if hasattr(self.scene(), 'views') and self.scene().views():
view = self.scene().views()[0]
if hasattr(view, 'zoom'):
zoom = view.zoom
if zoom <= 3:
return 0 # Lowest detail - no sockets visible
elif zoom <= 6:
return 1 # Medium detail - simple squares
else:
return 2 # High detail - full rendering
return 2 # Default to high detail
def paint(self, painter, QStyleOptionGraphicsItem, widget=None):
"""Painting a rectangle (performance optimized) with optional label"""
lod = self.getLOD()
if lod == 0:
# Don't draw sockets at very low zoom levels
return
elif lod == 1:
# Simple small rectangles
painter.setBrush(self._brush)
painter.setPen(Qt.NoPen)
painter.drawRect(-self.radius//2, -self.radius//2, self.radius, self.radius)
else:
# Full detail rectangles instead of circles for performance
painter.setBrush(self._brush)
painter.setPen(self._pen if not self.isHighlighted else self._pen_highlight)
painter.drawRect(-self.radius, -self.radius, 2 * self.radius, 2 * self.radius)
# Draw label if present and at high detail level
if hasattr(self.socket, 'label') and self.socket.label and lod == 2:
self.drawLabel(painter)
def drawLabel(self, painter):
"""Draw the socket label text"""
from nodeeditor.node_socket import LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM
painter.setFont(self.label_font)
painter.setPen(self.label_color)
# Calculate label position based on socket position
is_left_socket = self.socket.position in (LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM)
# Get text metrics for proper positioning
font_metrics = QFontMetrics(self.label_font)
text_width = font_metrics.horizontalAdvance(self.socket.label)
text_height = font_metrics.height()
if is_left_socket:
# Input socket - label on the right
label_x = self.radius + self.label_margin
label_y = text_height // 4 # Center vertically with socket
else:
# Output socket - label on the left
label_x = -self.radius - self.label_margin - text_width
label_y = text_height // 4 # Center vertically with socket
painter.drawText(label_x, label_y, self.socket.label)
def boundingRect(self) -> QRectF:
"""Defining Qt' bounding rectangle including label space"""
base_rect = QRectF(
- self.radius - self.outline_width,
- self.radius - self.outline_width,
2 * (self.radius + self.outline_width),
2 * (self.radius + self.outline_width),
)
# Expand bounding rect if there's a label
if hasattr(self.socket, 'label') and self.socket.label:
from nodeeditor.node_socket import LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM
font_metrics = QFontMetrics(self.label_font)
text_width = font_metrics.horizontalAdvance(self.socket.label)
text_height = font_metrics.height()
is_left_socket = self.socket.position in (LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM)
if is_left_socket:
# Input socket - label extends to the right
label_right = self.radius + self.label_margin + text_width
base_rect = base_rect.united(QRectF(
base_rect.left(),
-text_height // 2,
label_right - base_rect.left(),
text_height
))
else:
# Output socket - label extends to the left
label_left = -self.radius - self.label_margin - text_width
base_rect = base_rect.united(QRectF(
label_left,
-text_height // 2,
base_rect.right() - label_left,
text_height
))
return base_rect