nodebpy 0.13.0__tar.gz → 0.15.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nodebpy-0.13.0 → nodebpy-0.15.0}/PKG-INFO +1 -1
- {nodebpy-0.13.0 → nodebpy-0.15.0}/pyproject.toml +1 -1
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/__init__.py +1 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/__init__.py +2 -74
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/accessor.py +1 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/mixins.py +45 -25
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/node.py +9 -17
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/socket.py +218 -70
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/tree.py +157 -198
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/color.py +13 -13
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/converter.py +16 -16
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/distort.py +14 -14
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/filter.py +18 -18
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/group.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/input.py +13 -13
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/interface.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/manual.py +64 -17
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/matte.py +13 -13
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/output.py +3 -3
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/vector.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/__init__.py +6 -5
- nodebpy-0.15.0/src/nodebpy/nodes/geometry/attribute.py +291 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/color.py +3 -3
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/converter.py +55 -460
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/geometry.py +93 -93
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/grid.py +37 -37
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/group.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/input.py +77 -77
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/interface.py +8 -8
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/manual.py +1189 -254
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/output.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/texture.py +11 -11
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/utilities.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/vector.py +5 -5
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/zone.py +59 -53
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/color.py +5 -5
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/converter.py +7 -7
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/grid.py +6 -6
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/group.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/input.py +20 -20
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/manual.py +75 -14
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/output.py +6 -6
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/script.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/shader.py +21 -21
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/texture.py +5 -5
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/vector.py +8 -8
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/types.py +90 -23
- nodebpy-0.13.0/src/nodebpy/builder/interface.py +0 -571
- nodebpy-0.13.0/src/nodebpy/nodes/geometry/attribute.py +0 -723
- nodebpy-0.13.0/src/nodebpy/sockets.py +0 -48
- {nodebpy-0.13.0 → nodebpy-0.15.0}/README.md +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/arrange.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/_registry.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/builder/_utils.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/diagram.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/__init__.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/config.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/lib/nodearrange/utils.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/__init__.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/compositor/__init__.py +2 -2
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/geometry/groups.py +0 -0
- {nodebpy-0.13.0 → nodebpy-0.15.0}/src/nodebpy/nodes/shader/__init__.py +2 -2
|
@@ -1,31 +1,5 @@
|
|
|
1
|
-
"""nodebpy.builder — node tree construction API.
|
|
2
|
-
|
|
3
|
-
Public names are re-exported here. Old names (NodeBuilder, SocketLinker,
|
|
4
|
-
SocketBase) are kept as aliases for backward compatibility.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
1
|
from ._utils import SocketError, denormalize_name, normalize_name
|
|
8
2
|
from .accessor import SocketAccessor
|
|
9
|
-
from .interface import (
|
|
10
|
-
InterfaceSocket,
|
|
11
|
-
SocketBoolean,
|
|
12
|
-
SocketBundle,
|
|
13
|
-
SocketClosure,
|
|
14
|
-
SocketCollection,
|
|
15
|
-
SocketColor,
|
|
16
|
-
SocketFloat,
|
|
17
|
-
SocketGeometry,
|
|
18
|
-
SocketImage,
|
|
19
|
-
SocketInteger,
|
|
20
|
-
SocketMaterial,
|
|
21
|
-
SocketMatrix,
|
|
22
|
-
SocketMenu,
|
|
23
|
-
SocketObject,
|
|
24
|
-
SocketRotation,
|
|
25
|
-
SocketShader,
|
|
26
|
-
SocketString,
|
|
27
|
-
SocketVector,
|
|
28
|
-
)
|
|
29
3
|
from .mixins import LinkingMixin, OperatorMixin
|
|
30
4
|
from .node import (
|
|
31
5
|
BaseNode,
|
|
@@ -55,12 +29,6 @@ from .socket import (
|
|
|
55
29
|
Socket,
|
|
56
30
|
StringSocket,
|
|
57
31
|
VectorSocket,
|
|
58
|
-
_BooleanMixin,
|
|
59
|
-
_ColorMixin,
|
|
60
|
-
_IntegerMixin,
|
|
61
|
-
_MatrixMixin,
|
|
62
|
-
_RotationMixin,
|
|
63
|
-
_VectorMixin,
|
|
64
32
|
)
|
|
65
33
|
from .tree import (
|
|
66
34
|
InputInterfaceContext,
|
|
@@ -71,11 +39,6 @@ from .tree import (
|
|
|
71
39
|
TreeBuilder,
|
|
72
40
|
)
|
|
73
41
|
|
|
74
|
-
# Backward-compatible aliases for hand-written code that uses the old names.
|
|
75
|
-
NodeBuilder = BaseNode
|
|
76
|
-
SocketLinker = Socket
|
|
77
|
-
SocketBase = InterfaceSocket
|
|
78
|
-
|
|
79
42
|
__all__ = [
|
|
80
43
|
# Core
|
|
81
44
|
"TreeBuilder",
|
|
@@ -92,10 +55,7 @@ __all__ = [
|
|
|
92
55
|
"CustomCompositorGroup",
|
|
93
56
|
"CustomGeometryGroup",
|
|
94
57
|
"CustomShaderGroup",
|
|
95
|
-
|
|
96
|
-
"ShaderNodeGroup",
|
|
97
|
-
"CompositorNodeGroup",
|
|
98
|
-
# Type-specific socket classes (runtime)
|
|
58
|
+
# Runtime socket types
|
|
99
59
|
"FloatSocket",
|
|
100
60
|
"VectorSocket",
|
|
101
61
|
"ColorSocket",
|
|
@@ -114,35 +74,7 @@ __all__ = [
|
|
|
114
74
|
"BundleSocket",
|
|
115
75
|
"ClosureSocket",
|
|
116
76
|
"ShaderSocket",
|
|
117
|
-
#
|
|
118
|
-
"_VectorMixin",
|
|
119
|
-
"_ColorMixin",
|
|
120
|
-
"_IntegerMixin",
|
|
121
|
-
"_BooleanMixin",
|
|
122
|
-
"_RotationMixin",
|
|
123
|
-
"_MatrixMixin",
|
|
124
|
-
# Interface socket base
|
|
125
|
-
"InterfaceSocket",
|
|
126
|
-
# Interface socket types
|
|
127
|
-
"SocketFloat",
|
|
128
|
-
"SocketInteger",
|
|
129
|
-
"SocketBoolean",
|
|
130
|
-
"SocketVector",
|
|
131
|
-
"SocketColor",
|
|
132
|
-
"SocketRotation",
|
|
133
|
-
"SocketMatrix",
|
|
134
|
-
"SocketString",
|
|
135
|
-
"SocketMenu",
|
|
136
|
-
"SocketObject",
|
|
137
|
-
"SocketGeometry",
|
|
138
|
-
"SocketFont",
|
|
139
|
-
"SocketCollection",
|
|
140
|
-
"SocketImage",
|
|
141
|
-
"SocketMaterial",
|
|
142
|
-
"SocketBundle",
|
|
143
|
-
"SocketClosure",
|
|
144
|
-
"SocketShader",
|
|
145
|
-
# Tree context helpers
|
|
77
|
+
# Tree context
|
|
146
78
|
"SocketContext",
|
|
147
79
|
"PanelContext",
|
|
148
80
|
"InputInterfaceContext",
|
|
@@ -151,8 +83,4 @@ __all__ = [
|
|
|
151
83
|
"SocketError",
|
|
152
84
|
"normalize_name",
|
|
153
85
|
"denormalize_name",
|
|
154
|
-
# Backward-compatible aliases
|
|
155
|
-
"NodeBuilder",
|
|
156
|
-
"SocketLinker",
|
|
157
|
-
"SocketBase",
|
|
158
86
|
]
|
|
@@ -190,8 +190,7 @@ class SocketAccessor:
|
|
|
190
190
|
return len(self._items())
|
|
191
191
|
|
|
192
192
|
def __iter__(self):
|
|
193
|
-
|
|
194
|
-
return iter(self._keys())
|
|
193
|
+
return iter(self._values())
|
|
195
194
|
|
|
196
195
|
def __getattr__(self, name: str) -> "Socket":
|
|
197
196
|
"""Dynamic socket access by normalised attribute name.
|
|
@@ -11,10 +11,11 @@ from ._utils import SocketError, _resolve_promotion, _SocketLike
|
|
|
11
11
|
_RShiftT = TypeVar("_RShiftT")
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from ..nodes.geometry import Compare, Math
|
|
14
|
+
from ..nodes.geometry import Compare, Math, MultiplyMatrices, TransformPoint
|
|
15
15
|
from ..types import InputLinkable
|
|
16
16
|
from .node import BaseNode
|
|
17
|
-
from .socket import Socket
|
|
17
|
+
from .socket import MatrixSocket, Socket
|
|
18
|
+
from .tree import TreeBuilder
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class OperatorMixin:
|
|
@@ -160,46 +161,46 @@ class OperatorMixin:
|
|
|
160
161
|
return BooleanMath.l_not(self)
|
|
161
162
|
|
|
162
163
|
@staticmethod
|
|
163
|
-
def _cast_to_matrix(value):
|
|
164
|
+
def _cast_to_matrix(value) -> MatrixSocket:
|
|
164
165
|
from ..nodes.geometry.converter import CombineMatrix
|
|
165
166
|
|
|
166
167
|
if hasattr(value, "shape") and value.shape == (4, 4):
|
|
167
|
-
return CombineMatrix(*value.ravel())
|
|
168
|
+
return CombineMatrix(*value.ravel()).o.matrix
|
|
168
169
|
else:
|
|
169
170
|
return value
|
|
170
171
|
|
|
171
|
-
def __matmul__(self, other: Any):
|
|
172
|
+
def __matmul__(self, other: Any) -> "MultiplyMatrices | TransformPoint":
|
|
172
173
|
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
173
174
|
|
|
174
175
|
other = self._cast_to_matrix(other)
|
|
175
|
-
socket = self._default_output_socket
|
|
176
|
-
other_type = getattr(other, "type", None)
|
|
176
|
+
socket = self._default_output_socket
|
|
177
177
|
|
|
178
|
-
if socket.type == "MATRIX" and
|
|
178
|
+
if socket.type == "MATRIX" and other.type == "VECTOR":
|
|
179
179
|
return TransformPoint(other, socket)
|
|
180
180
|
|
|
181
|
-
return MultiplyMatrices(
|
|
181
|
+
return MultiplyMatrices(socket, other)
|
|
182
182
|
|
|
183
|
-
def __rmatmul__(self, other: Any):
|
|
183
|
+
def __rmatmul__(self, other: Any) -> "MultiplyMatrices | TransformPoint":
|
|
184
184
|
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
185
185
|
|
|
186
186
|
other = self._cast_to_matrix(other)
|
|
187
|
-
socket = self._default_output_socket
|
|
188
|
-
other_type = getattr(other, "type", None)
|
|
187
|
+
socket = self._default_output_socket
|
|
189
188
|
|
|
190
|
-
if socket.type == "VECTOR" and
|
|
189
|
+
if socket.type == "VECTOR" and getattr(other, "type", None) == "MATRIX":
|
|
191
190
|
return TransformPoint(socket, other)
|
|
192
191
|
|
|
193
|
-
return MultiplyMatrices(other,
|
|
192
|
+
return MultiplyMatrices(other, socket)
|
|
194
193
|
|
|
195
194
|
|
|
196
195
|
class LinkingMixin:
|
|
197
196
|
"""Node/socket linking logic: ``>>``, ``_link``, best-socket matching.
|
|
198
197
|
|
|
199
|
-
Requires ``tree``, ``
|
|
198
|
+
Requires ``tree``, ``i``, ``o``, ``_default_output_socket``,
|
|
200
199
|
and ``_default_input_socket`` on the concrete class.
|
|
201
200
|
"""
|
|
202
201
|
|
|
202
|
+
tree: "TreeBuilder"
|
|
203
|
+
|
|
203
204
|
def _source_socket(self, node: "InputLinkable | Socket | NodeSocket") -> NodeSocket:
|
|
204
205
|
assert node
|
|
205
206
|
if isinstance(node, NodeSocket):
|
|
@@ -224,18 +225,22 @@ class LinkingMixin:
|
|
|
224
225
|
target: "BaseNode | Socket | NodeSocket | EllipsisType | LinkingMixin",
|
|
225
226
|
) -> tuple[NodeSocket, NodeSocket]:
|
|
226
227
|
"""Find the best compatible pair of sockets between two nodes/sockets."""
|
|
227
|
-
from ..
|
|
228
|
+
from ..builder.node import BaseNode
|
|
229
|
+
from ..builder.socket import Socket
|
|
230
|
+
from ..types import PREFER_FIRST_SOCKET, SOCKET_COMPATIBILITY
|
|
228
231
|
|
|
229
232
|
possible_combos = []
|
|
230
|
-
if
|
|
231
|
-
outputs = source.
|
|
233
|
+
if isinstance(source, BaseNode):
|
|
234
|
+
outputs = source.o._available
|
|
232
235
|
elif isinstance(source, NodeSocket):
|
|
233
236
|
outputs = [source]
|
|
237
|
+
elif isinstance(source, Socket):
|
|
238
|
+
outputs = [source.socket]
|
|
234
239
|
else:
|
|
235
240
|
raise TypeError(f"Cannot get outputs from {type(source)}")
|
|
236
241
|
|
|
237
|
-
if
|
|
238
|
-
inputs = target.
|
|
242
|
+
if isinstance(target, BaseNode):
|
|
243
|
+
inputs = target.i._available
|
|
239
244
|
else:
|
|
240
245
|
inputs = [target]
|
|
241
246
|
|
|
@@ -244,6 +249,21 @@ class LinkingMixin:
|
|
|
244
249
|
if outputs and inputs:
|
|
245
250
|
return inputs[0], outputs[0]
|
|
246
251
|
|
|
252
|
+
# Try first available input first — if the output type matches it exactly,
|
|
253
|
+
# or is a "preferred" implicit conversion (e.g. float→color, vector→color),
|
|
254
|
+
# use the first socket rather than searching for a better-typed later one.
|
|
255
|
+
# This keeps float→Image working in the compositor instead of drifting to
|
|
256
|
+
# a float Factor socket that scores higher on raw compatibility.
|
|
257
|
+
# Pairs not in PREFER_FIRST_SOCKET (e.g. VALUE→BOOLEAN, VECTOR→ROTATION)
|
|
258
|
+
# fall through to the ranked search below.
|
|
259
|
+
if inputs:
|
|
260
|
+
first_input = inputs[0]
|
|
261
|
+
for output in outputs:
|
|
262
|
+
if first_input.type == output.type:
|
|
263
|
+
return first_input, output
|
|
264
|
+
if (output.type, first_input.type) in PREFER_FIRST_SOCKET:
|
|
265
|
+
return first_input, output
|
|
266
|
+
|
|
247
267
|
for output in outputs:
|
|
248
268
|
compat_sockets = SOCKET_COMPATIBILITY.get(output.type, ())
|
|
249
269
|
for input in inputs:
|
|
@@ -269,7 +289,7 @@ class LinkingMixin:
|
|
|
269
289
|
) -> NodeLink:
|
|
270
290
|
source_socket = self._source_socket(source)
|
|
271
291
|
target_socket = self._target_socket(target)
|
|
272
|
-
return self.tree.link(source_socket, target_socket)
|
|
292
|
+
return self.tree.link(source_socket, target_socket)
|
|
273
293
|
|
|
274
294
|
def _link_from(
|
|
275
295
|
self,
|
|
@@ -278,9 +298,9 @@ class LinkingMixin:
|
|
|
278
298
|
):
|
|
279
299
|
if isinstance(input, str):
|
|
280
300
|
try:
|
|
281
|
-
self._link(source, self.node.inputs[input])
|
|
301
|
+
self._link(source, self.node.inputs[input])
|
|
282
302
|
except KeyError:
|
|
283
|
-
self._link(source, self.node.inputs[self.
|
|
303
|
+
self._link(source, self.node.inputs[self.i._index(input)])
|
|
284
304
|
else:
|
|
285
305
|
self._link(source, input)
|
|
286
306
|
|
|
@@ -304,8 +324,8 @@ class LinkingMixin:
|
|
|
304
324
|
try:
|
|
305
325
|
target = other.node.inputs[name]
|
|
306
326
|
except KeyError:
|
|
307
|
-
target = other.node.inputs[other.
|
|
308
|
-
source = self.
|
|
327
|
+
target = other.node.inputs[other.i._index(name)]
|
|
328
|
+
source = self.o._best_match(target.type) if hasattr(self, "o") else self
|
|
309
329
|
else:
|
|
310
330
|
try:
|
|
311
331
|
source, target = self._find_best_socket_pair(self, other)
|
|
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
|
|
|
41
41
|
def _add_inputs(self, *args: Any, **kwargs: Any) -> dict[str, NodeSocket]: ...
|
|
42
42
|
|
|
43
43
|
@property
|
|
44
|
-
def
|
|
44
|
+
def i(self) -> SocketAccessor: ...
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
@@ -84,13 +84,13 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
84
84
|
@property
|
|
85
85
|
def _default_input_socket(self) -> NodeSocket:
|
|
86
86
|
if self._default_input_id is not None:
|
|
87
|
-
return self.node.inputs[self.
|
|
87
|
+
return self.node.inputs[self.i._index(self._default_input_id)]
|
|
88
88
|
return self.node.inputs[0]
|
|
89
89
|
|
|
90
90
|
@property
|
|
91
91
|
def _default_output_socket(self) -> NodeSocket:
|
|
92
92
|
if self._default_output_id is not None:
|
|
93
|
-
return self.node.outputs[self.
|
|
93
|
+
return self.node.outputs[self.o._index(self._default_output_id)]
|
|
94
94
|
|
|
95
95
|
counter = 0
|
|
96
96
|
socket = self.node.outputs[counter]
|
|
@@ -115,7 +115,7 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
115
115
|
if link.to_node.bl_idname == cls._bl_idname:
|
|
116
116
|
return cls._from_node(link.to_node)
|
|
117
117
|
node = cls()
|
|
118
|
-
node.tree.link(socket, node.
|
|
118
|
+
node.tree.link(socket, node.i._best_match(socket.type))
|
|
119
119
|
return node
|
|
120
120
|
else:
|
|
121
121
|
if socket.links:
|
|
@@ -163,9 +163,7 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
163
163
|
elif isinstance(value, NodeSocket):
|
|
164
164
|
self._link_from(value, name)
|
|
165
165
|
elif isinstance(value, _NodeLike):
|
|
166
|
-
self._link_from(
|
|
167
|
-
value.outputs._best_match(self.inputs._get(name).type), name
|
|
168
|
-
)
|
|
166
|
+
self._link_from(value.o._best_match(self.i._get(name).type), name)
|
|
169
167
|
else:
|
|
170
168
|
if name in input_ids:
|
|
171
169
|
input = self.node.inputs[input_ids.index(name)]
|
|
@@ -177,14 +175,6 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
177
175
|
input = self.node.inputs[name.replace("_", " ").title()]
|
|
178
176
|
self._set_input_default_value(input, value)
|
|
179
177
|
|
|
180
|
-
@property
|
|
181
|
-
def outputs(self) -> SocketAccessor:
|
|
182
|
-
return SocketAccessor(self.node.outputs, "output")
|
|
183
|
-
|
|
184
|
-
@property
|
|
185
|
-
def inputs(self) -> SocketAccessor:
|
|
186
|
-
return SocketAccessor(self.node.inputs, "input")
|
|
187
|
-
|
|
188
178
|
@property
|
|
189
179
|
def o(self) -> SocketAccessor:
|
|
190
180
|
"""Output socket accessor. Subclasses narrow the return type via TYPE_CHECKING."""
|
|
@@ -225,7 +215,7 @@ class DynamicInputsMixin(ABC):
|
|
|
225
215
|
except SocketError:
|
|
226
216
|
dyn = cast("_DynamicTarget", target)
|
|
227
217
|
target_name, source_socket = list(dyn._add_inputs(source).items())[0]
|
|
228
|
-
return (source_socket, dyn.
|
|
218
|
+
return (source_socket, dyn.i[target_name].socket)
|
|
229
219
|
|
|
230
220
|
@abstractmethod
|
|
231
221
|
def _add_socket(self, name: str, *args: Any, **kwargs: Any) -> NodeSocket: ...
|
|
@@ -238,7 +228,9 @@ class DynamicInputsMixin(ABC):
|
|
|
238
228
|
items[arg._default_output_socket.name] = arg
|
|
239
229
|
items.update(kwargs)
|
|
240
230
|
for key, source in items.items():
|
|
241
|
-
socket_source, type = self._match_compatible_data(
|
|
231
|
+
socket_source, type = self._match_compatible_data(
|
|
232
|
+
source.o._available if hasattr(source, "o") else [source]
|
|
233
|
+
)
|
|
242
234
|
if type in self._type_map:
|
|
243
235
|
type = self._type_map[type]
|
|
244
236
|
socket = self._add_socket(name=key, type=type)
|