Spacebar menu: remove references to removed operators
[blender-addons.git] / node_wrangler / utils / draw.py
blob1851852cfbf42a33688afc14328e42f16aed90b8
1 # SPDX-FileCopyrightText: 2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import bpy
6 import gpu
7 from gpu_extras.batch import batch_for_shader
8 from math import cos, sin, pi
10 from .nodes import get_nodes_links, prefs_line_width, abs_node_location, dpi_fac
13 def draw_line(x1, y1, x2, y2, size, colour=(1.0, 1.0, 1.0, 0.7)):
14 shader = gpu.shader.from_builtin('POLYLINE_SMOOTH_COLOR')
15 shader.uniform_float("viewportSize", gpu.state.viewport_get()[2:])
16 shader.uniform_float("lineWidth", size * prefs_line_width())
18 vertices = ((x1, y1), (x2, y2))
19 vertex_colors = ((colour[0] + (1.0 - colour[0]) / 4,
20 colour[1] + (1.0 - colour[1]) / 4,
21 colour[2] + (1.0 - colour[2]) / 4,
22 colour[3] + (1.0 - colour[3]) / 4),
23 colour)
25 batch = batch_for_shader(shader, 'LINE_STRIP', {"pos": vertices, "color": vertex_colors})
26 batch.draw(shader)
29 def draw_circle_2d_filled(mx, my, radius, colour=(1.0, 1.0, 1.0, 0.7)):
30 radius = radius * prefs_line_width()
31 sides = 12
32 vertices = [(radius * cos(i * 2 * pi / sides) + mx,
33 radius * sin(i * 2 * pi / sides) + my)
34 for i in range(sides + 1)]
36 shader = gpu.shader.from_builtin('UNIFORM_COLOR')
37 shader.uniform_float("color", colour)
38 batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices})
39 batch.draw(shader)
42 def draw_rounded_node_border(node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)):
43 area_width = bpy.context.area.width
44 sides = 16
45 radius *= prefs_line_width()
47 nlocx, nlocy = abs_node_location(node)
49 nlocx = (nlocx + 1) * dpi_fac()
50 nlocy = (nlocy + 1) * dpi_fac()
51 ndimx = node.dimensions.x
52 ndimy = node.dimensions.y
54 if node.hide:
55 nlocx += -1
56 nlocy += 5
57 if node.type == 'REROUTE':
58 # nlocx += 1
59 nlocy -= 1
60 ndimx = 0
61 ndimy = 0
62 radius += 6
64 shader = gpu.shader.from_builtin('UNIFORM_COLOR')
65 shader.uniform_float("color", colour)
67 # Top left corner
68 mx, my = bpy.context.region.view2d.view_to_region(nlocx, nlocy, clip=False)
69 vertices = [(mx, my)]
70 for i in range(sides + 1):
71 if (4 <= i <= 8):
72 if mx < area_width:
73 cosine = radius * cos(i * 2 * pi / sides) + mx
74 sine = radius * sin(i * 2 * pi / sides) + my
75 vertices.append((cosine, sine))
77 batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices})
78 batch.draw(shader)
80 # Top right corner
81 mx, my = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False)
82 vertices = [(mx, my)]
83 for i in range(sides + 1):
84 if (0 <= i <= 4):
85 if mx < area_width:
86 cosine = radius * cos(i * 2 * pi / sides) + mx
87 sine = radius * sin(i * 2 * pi / sides) + my
88 vertices.append((cosine, sine))
90 batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices})
91 batch.draw(shader)
93 # Bottom left corner
94 mx, my = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False)
95 vertices = [(mx, my)]
96 for i in range(sides + 1):
97 if (8 <= i <= 12):
98 if mx < area_width:
99 cosine = radius * cos(i * 2 * pi / sides) + mx
100 sine = radius * sin(i * 2 * pi / sides) + my
101 vertices.append((cosine, sine))
103 batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices})
104 batch.draw(shader)
106 # Bottom right corner
107 mx, my = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False)
108 vertices = [(mx, my)]
109 for i in range(sides + 1):
110 if (12 <= i <= 16):
111 if mx < area_width:
112 cosine = radius * cos(i * 2 * pi / sides) + mx
113 sine = radius * sin(i * 2 * pi / sides) + my
114 vertices.append((cosine, sine))
116 batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices})
117 batch.draw(shader)
119 # prepare drawing all edges in one batch
120 vertices = []
121 indices = []
122 id_last = 0
124 # Left edge
125 m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy, clip=False)
126 m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False)
127 if m1x < area_width and m2x < area_width:
128 vertices.extend([(m2x - radius, m2y), (m2x, m2y),
129 (m1x, m1y), (m1x - radius, m1y)])
130 indices.extend([(id_last, id_last + 1, id_last + 3),
131 (id_last + 3, id_last + 1, id_last + 2)])
132 id_last += 4
134 # Top edge
135 m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy, clip=False)
136 m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False)
137 m1x = min(m1x, area_width)
138 m2x = min(m2x, area_width)
139 vertices.extend([(m1x, m1y), (m2x, m1y),
140 (m2x, m1y + radius), (m1x, m1y + radius)])
141 indices.extend([(id_last, id_last + 1, id_last + 3),
142 (id_last + 3, id_last + 1, id_last + 2)])
143 id_last += 4
145 # Right edge
146 m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False)
147 m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False)
148 if m1x < area_width and m2x < area_width:
149 vertices.extend([(m1x, m2y), (m1x + radius, m2y),
150 (m1x + radius, m1y), (m1x, m1y)])
151 indices.extend([(id_last, id_last + 1, id_last + 3),
152 (id_last + 3, id_last + 1, id_last + 2)])
153 id_last += 4
155 # Bottom edge
156 m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False)
157 m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False)
158 m1x = min(m1x, area_width)
159 m2x = min(m2x, area_width)
160 vertices.extend([(m1x, m2y), (m2x, m2y),
161 (m2x, m1y - radius), (m1x, m1y - radius)])
162 indices.extend([(id_last, id_last + 1, id_last + 3),
163 (id_last + 3, id_last + 1, id_last + 2)])
165 # now draw all edges in one batch
166 if len(vertices) != 0:
167 batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)
168 batch.draw(shader)
171 def draw_callback_nodeoutline(self, context, mode):
172 if self.mouse_path:
173 gpu.state.blend_set('ALPHA')
175 nodes, _links = get_nodes_links(context)
177 if mode == "LINK":
178 col_outer = (1.0, 0.2, 0.2, 0.4)
179 col_inner = (0.0, 0.0, 0.0, 0.5)
180 col_circle_inner = (0.3, 0.05, 0.05, 1.0)
181 elif mode == "LINKMENU":
182 col_outer = (0.4, 0.6, 1.0, 0.4)
183 col_inner = (0.0, 0.0, 0.0, 0.5)
184 col_circle_inner = (0.08, 0.15, .3, 1.0)
185 elif mode == "MIX":
186 col_outer = (0.2, 1.0, 0.2, 0.4)
187 col_inner = (0.0, 0.0, 0.0, 0.5)
188 col_circle_inner = (0.05, 0.3, 0.05, 1.0)
190 m1x = self.mouse_path[0][0]
191 m1y = self.mouse_path[0][1]
192 m2x = self.mouse_path[-1][0]
193 m2y = self.mouse_path[-1][1]
195 n1 = nodes[context.scene.NWLazySource]
196 n2 = nodes[context.scene.NWLazyTarget]
198 if n1 == n2:
199 col_outer = (0.4, 0.4, 0.4, 0.4)
200 col_inner = (0.0, 0.0, 0.0, 0.5)
201 col_circle_inner = (0.2, 0.2, 0.2, 1.0)
203 draw_rounded_node_border(n1, radius=6, colour=col_outer) # outline
204 draw_rounded_node_border(n1, radius=5, colour=col_inner) # inner
205 draw_rounded_node_border(n2, radius=6, colour=col_outer) # outline
206 draw_rounded_node_border(n2, radius=5, colour=col_inner) # inner
208 draw_line(m1x, m1y, m2x, m2y, 5, col_outer) # line outline
209 draw_line(m1x, m1y, m2x, m2y, 2, col_inner) # line inner
211 # circle outline
212 draw_circle_2d_filled(m1x, m1y, 7, col_outer)
213 draw_circle_2d_filled(m2x, m2y, 7, col_outer)
215 # circle inner
216 draw_circle_2d_filled(m1x, m1y, 5, col_circle_inner)
217 draw_circle_2d_filled(m2x, m2y, 5, col_circle_inner)
219 gpu.state.blend_set('NONE')