nodebpy 0.18.0__tar.gz → 520.0.1__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.18.0 → nodebpy-520.0.1}/PKG-INFO +2 -2
- {nodebpy-0.18.0 → nodebpy-520.0.1}/pyproject.toml +2 -3
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/__init__.py +51 -0
- nodebpy-520.0.1/src/nodebpy/builder/_registry.py +26 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/_utils.py +1 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/accessor.py +5 -5
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/mixins.py +67 -50
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/node.py +27 -10
- nodebpy-520.0.1/src/nodebpy/builder/socket.py +2457 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/builder/tree.py +13 -4
- nodebpy-520.0.1/src/nodebpy/lib/nodearrange/arrange/__init__.py +1 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/__init__.py +91 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/color.py +9 -9
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/converter.py +352 -311
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/distort.py +19 -11
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/filter.py +13 -13
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/group.py +1 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/input.py +176 -16
- nodebpy-520.0.1/src/nodebpy/nodes/compositor/interface.py +242 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/matte.py +11 -11
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/output.py +15 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/vector.py +5 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/__init__.py +61 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/attribute.py +135 -23
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/color.py +6 -6
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/converter.py +2828 -812
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/geometry.py +926 -74
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/grid.py +207 -190
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/group.py +1 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/groups.py +51 -14
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/input.py +184 -35
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/interface.py +77 -52
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/manual.py +663 -84
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/output.py +1 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/texture.py +10 -10
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/utilities.py +7 -16
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/vector.py +6 -6
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/geometry/zone.py +8 -11
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/__init__.py +22 -8
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/color.py +6 -6
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/converter.py +178 -29
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/grid.py +10 -10
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/group.py +1 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/input.py +7 -7
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/output.py +9 -9
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/script.py +1 -1
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/shader.py +41 -17
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/texture.py +7 -7
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/vector.py +7 -7
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/types.py +114 -13
- nodebpy-0.18.0/src/nodebpy/builder/_registry.py +0 -19
- nodebpy-0.18.0/src/nodebpy/builder/socket.py +0 -1866
- nodebpy-0.18.0/src/nodebpy/nodes/compositor/interface.py +0 -149
- {nodebpy-0.18.0 → nodebpy-520.0.1}/README.md +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/__init__.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/arrange.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/diagram.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/__init__.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/config.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/lib/nodearrange/utils.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/__init__.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/compositor/manual.py +0 -0
- {nodebpy-0.18.0 → nodebpy-520.0.1}/src/nodebpy/nodes/shader/manual.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nodebpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 520.0.1
|
|
4
4
|
Summary: Build nodes trees in Blender more elegantly with code
|
|
5
5
|
Author: Brady Johnston
|
|
6
6
|
Author-email: Brady Johnston <brady.johnston@me.com>
|
|
7
7
|
License: GPL-3.0-or-later
|
|
8
|
-
Requires-Dist: bpy
|
|
8
|
+
Requires-Dist: bpy==5.2.* ; extra == 'bpy'
|
|
9
9
|
Requires-Dist: networkx>=3.6.1 ; extra == 'networkx'
|
|
10
10
|
Requires-Python: >=3.13
|
|
11
11
|
Provides-Extra: bpy
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nodebpy"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "520.0.1"
|
|
4
4
|
description = "Build nodes trees in Blender more elegantly with code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -17,7 +17,7 @@ networkx = [
|
|
|
17
17
|
"networkx>=3.6.1",
|
|
18
18
|
]
|
|
19
19
|
bpy = [
|
|
20
|
-
"bpy
|
|
20
|
+
"bpy==5.2.*",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[build-system]
|
|
@@ -36,7 +36,6 @@ dev = [
|
|
|
36
36
|
"quartodoc>=0.11.1",
|
|
37
37
|
"ruff>=0.14.11",
|
|
38
38
|
"syrupy>=5.0.0",
|
|
39
|
-
"tree-clipper>=0.1.1",
|
|
40
39
|
"pytest-xdist>=3.8.0",
|
|
41
40
|
"griffe<2.0.0",
|
|
42
41
|
"ty>=0.0.35",
|
|
@@ -11,24 +11,49 @@ from .node import (
|
|
|
11
11
|
)
|
|
12
12
|
from .socket import (
|
|
13
13
|
BooleanSocket,
|
|
14
|
+
BooleanSocketGrid,
|
|
15
|
+
BooleanSocketList,
|
|
14
16
|
BundleSocket,
|
|
17
|
+
BundleSocketList,
|
|
15
18
|
ClosureSocket,
|
|
19
|
+
ClosureSocketList,
|
|
16
20
|
CollectionSocket,
|
|
21
|
+
CollectionSocketList,
|
|
17
22
|
ColorSocket,
|
|
23
|
+
ColorSocketList,
|
|
18
24
|
FloatSocket,
|
|
25
|
+
FloatSocketGrid,
|
|
26
|
+
FloatSocketList,
|
|
19
27
|
FontSocket,
|
|
28
|
+
FontSocketList,
|
|
20
29
|
GeometrySocket,
|
|
30
|
+
GeometrySocketList,
|
|
21
31
|
ImageSocket,
|
|
32
|
+
ImageSocketList,
|
|
22
33
|
IntegerSocket,
|
|
34
|
+
IntegerSocketGrid,
|
|
35
|
+
IntegerSocketList,
|
|
36
|
+
IntegerVectorSocket,
|
|
23
37
|
MaterialSocket,
|
|
38
|
+
MaterialSocketList,
|
|
24
39
|
MatrixSocket,
|
|
40
|
+
MatrixSocketList,
|
|
25
41
|
MenuSocket,
|
|
42
|
+
MenuSocketList,
|
|
26
43
|
ObjectSocket,
|
|
44
|
+
ObjectSocketList,
|
|
27
45
|
RotationSocket,
|
|
46
|
+
RotationSocketList,
|
|
28
47
|
ShaderSocket,
|
|
48
|
+
ShaderSocketList,
|
|
29
49
|
Socket,
|
|
50
|
+
SoundSocket,
|
|
51
|
+
SoundSocketList,
|
|
30
52
|
StringSocket,
|
|
53
|
+
StringSocketList,
|
|
31
54
|
VectorSocket,
|
|
55
|
+
VectorSocketGrid,
|
|
56
|
+
VectorSocketList,
|
|
32
57
|
)
|
|
33
58
|
from .tree import (
|
|
34
59
|
InputInterfaceContext,
|
|
@@ -55,25 +80,51 @@ __all__ = [
|
|
|
55
80
|
"CustomCompositorGroup",
|
|
56
81
|
"CustomGeometryGroup",
|
|
57
82
|
"CustomShaderGroup",
|
|
83
|
+
"CustomShaderGroup",
|
|
58
84
|
# Runtime socket types
|
|
59
85
|
"FloatSocket",
|
|
86
|
+
"FloatSocketGrid",
|
|
87
|
+
"FloatSocketList",
|
|
60
88
|
"VectorSocket",
|
|
89
|
+
"VectorSocketGrid",
|
|
90
|
+
"VectorSocketList",
|
|
61
91
|
"ColorSocket",
|
|
92
|
+
"ColorSocketList",
|
|
62
93
|
"IntegerSocket",
|
|
94
|
+
"IntegerVectorSocket",
|
|
95
|
+
"IntegerSocketGrid",
|
|
96
|
+
"IntegerSocketList",
|
|
63
97
|
"BooleanSocket",
|
|
98
|
+
"BooleanSocketGrid",
|
|
99
|
+
"BooleanSocketList",
|
|
64
100
|
"RotationSocket",
|
|
101
|
+
"RotationSocketList",
|
|
65
102
|
"MatrixSocket",
|
|
103
|
+
"MatrixSocketList",
|
|
66
104
|
"StringSocket",
|
|
105
|
+
"StringSocketList",
|
|
67
106
|
"MenuSocket",
|
|
107
|
+
"MenuSocketList",
|
|
68
108
|
"GeometrySocket",
|
|
109
|
+
"GeometrySocketList",
|
|
69
110
|
"ObjectSocket",
|
|
111
|
+
"ObjectSocketList",
|
|
70
112
|
"FontSocket",
|
|
113
|
+
"FontSocketList",
|
|
71
114
|
"MaterialSocket",
|
|
115
|
+
"MaterialSocketList",
|
|
72
116
|
"ImageSocket",
|
|
117
|
+
"ImageSocketList",
|
|
73
118
|
"CollectionSocket",
|
|
119
|
+
"CollectionSocketList",
|
|
74
120
|
"BundleSocket",
|
|
121
|
+
"BundleSocketList",
|
|
75
122
|
"ClosureSocket",
|
|
123
|
+
"ClosureSocketList",
|
|
76
124
|
"ShaderSocket",
|
|
125
|
+
"ShaderSocketList",
|
|
126
|
+
"SoundSocket",
|
|
127
|
+
"SoundSocketList",
|
|
77
128
|
# Tree context
|
|
78
129
|
"SocketContext",
|
|
79
130
|
"PanelContext",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from bpy.types import NodeSocket
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .socket import Socket
|
|
9
|
+
|
|
10
|
+
_SOCKET_REGISTRY: dict[str, "type[Socket]"] = {}
|
|
11
|
+
_SOCKET_LIST_REGISTRY: dict[str, "type[Socket]"] = {}
|
|
12
|
+
_SOCKET_GRID_REGISTRY: dict[str, "type[Socket]"] = {}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _wrap_socket(socket: NodeSocket) -> "Socket":
|
|
16
|
+
for key, cls in _SOCKET_REGISTRY.items():
|
|
17
|
+
if key in socket.bl_idname:
|
|
18
|
+
structure = getattr(socket, "inferred_structure_type", "SINGLE")
|
|
19
|
+
if structure == "LIST":
|
|
20
|
+
return _SOCKET_LIST_REGISTRY.get(key, cls)(socket)
|
|
21
|
+
elif structure == "GRID":
|
|
22
|
+
return _SOCKET_GRID_REGISTRY.get(key, cls)(socket)
|
|
23
|
+
return cls(socket)
|
|
24
|
+
from .socket import Socket
|
|
25
|
+
|
|
26
|
+
return Socket(socket)
|
|
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Iterator, Literal, overload
|
|
|
5
5
|
import bpy
|
|
6
6
|
from bpy.types import NodeSocket
|
|
7
7
|
|
|
8
|
-
from ._registry import
|
|
8
|
+
from ._registry import _wrap_socket
|
|
9
9
|
from ._utils import (
|
|
10
10
|
SocketError,
|
|
11
11
|
_allow_innactive_sockets,
|
|
@@ -79,14 +79,14 @@ class SocketAccessor:
|
|
|
79
79
|
"""Get a Socket for a socket by identifier, name, or index."""
|
|
80
80
|
if isinstance(key, slice):
|
|
81
81
|
sockets = [
|
|
82
|
-
|
|
82
|
+
_wrap_socket(self._collection[i])
|
|
83
83
|
for i in range(*key.indices(len(self._collection)))
|
|
84
84
|
]
|
|
85
85
|
if self._builder is not None:
|
|
86
86
|
for s in sockets:
|
|
87
87
|
s._builder_node = self._builder
|
|
88
88
|
return sockets
|
|
89
|
-
socket =
|
|
89
|
+
socket = _wrap_socket(self._collection[self._index(key)])
|
|
90
90
|
if self._builder is not None:
|
|
91
91
|
socket._builder_node = self._builder
|
|
92
92
|
return socket
|
|
@@ -185,7 +185,7 @@ class SocketAccessor:
|
|
|
185
185
|
Uses node-level visibility rules regardless of ``ignore_visibility`` —
|
|
186
186
|
see ``_visible_sockets`` for rationale.
|
|
187
187
|
"""
|
|
188
|
-
return [
|
|
188
|
+
return [_wrap_socket(s) for s in self._visible_sockets()]
|
|
189
189
|
|
|
190
190
|
def _items(self) -> "list[tuple[str, Socket]]":
|
|
191
191
|
"""All visible sockets as (name, Socket) pairs.
|
|
@@ -193,7 +193,7 @@ class SocketAccessor:
|
|
|
193
193
|
Uses node-level visibility rules regardless of ``ignore_visibility`` —
|
|
194
194
|
see ``_visible_sockets`` for rationale.
|
|
195
195
|
"""
|
|
196
|
-
return [(s.name,
|
|
196
|
+
return [(s.name, _wrap_socket(s)) for s in self._visible_sockets()]
|
|
197
197
|
|
|
198
198
|
def _keys(self) -> list[str]:
|
|
199
199
|
"""All visible socket names."""
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from types import EllipsisType
|
|
4
|
-
from typing import TYPE_CHECKING, Any, TypeVar, cast, overload
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast, overload
|
|
5
5
|
|
|
6
6
|
from bpy.types import NodeLink, NodeSocket
|
|
7
7
|
|
|
8
|
-
from ._registry import
|
|
8
|
+
from ._registry import _wrap_socket
|
|
9
9
|
from ._utils import SocketError, _resolve_promotion, _SocketLike
|
|
10
10
|
|
|
11
11
|
_RShiftT = TypeVar("_RShiftT")
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
+
from ..nodes.geometry import CombineTransform
|
|
14
15
|
from ..types import InputLinkable
|
|
15
16
|
from .accessor import SocketAccessor
|
|
16
17
|
from .node import BaseNode
|
|
@@ -19,6 +20,7 @@ if TYPE_CHECKING:
|
|
|
19
20
|
FloatSocket,
|
|
20
21
|
IntegerSocket,
|
|
21
22
|
MatrixSocket,
|
|
23
|
+
Position,
|
|
22
24
|
Socket,
|
|
23
25
|
VectorSocket,
|
|
24
26
|
)
|
|
@@ -30,7 +32,7 @@ class OperatorMixin:
|
|
|
30
32
|
|
|
31
33
|
Requires ``_default_output_socket`` on the concrete class.
|
|
32
34
|
Delegates all dispatch to type-specific ``_dispatch_*`` methods on Socket
|
|
33
|
-
subclasses, looked up via ``
|
|
35
|
+
subclasses, looked up via ``_wrap_socket``.
|
|
34
36
|
"""
|
|
35
37
|
|
|
36
38
|
__array_ufunc__ = None
|
|
@@ -48,7 +50,7 @@ class OperatorMixin:
|
|
|
48
50
|
other,
|
|
49
51
|
reverse,
|
|
50
52
|
)
|
|
51
|
-
return
|
|
53
|
+
return _wrap_socket(socket)._dispatch_math(other, operation, reverse)
|
|
52
54
|
|
|
53
55
|
def __mul__(self, other: Any) -> "FloatSocket | VectorSocket | IntegerSocket":
|
|
54
56
|
return self._apply_math_operation(other, "multiply")
|
|
@@ -92,7 +94,7 @@ class OperatorMixin:
|
|
|
92
94
|
other,
|
|
93
95
|
False,
|
|
94
96
|
)
|
|
95
|
-
return
|
|
97
|
+
return _wrap_socket(socket)._dispatch_floordiv(other, reverse)
|
|
96
98
|
|
|
97
99
|
def __rfloordiv__(self, other: Any) -> "FloatSocket | VectorSocket | IntegerSocket":
|
|
98
100
|
socket, other, reverse = _resolve_promotion(
|
|
@@ -100,15 +102,66 @@ class OperatorMixin:
|
|
|
100
102
|
other,
|
|
101
103
|
True,
|
|
102
104
|
)
|
|
103
|
-
return
|
|
105
|
+
return _wrap_socket(socket)._dispatch_floordiv(other, reverse)
|
|
106
|
+
|
|
107
|
+
@overload
|
|
108
|
+
def __matmul__(self, other: "Position") -> "VectorSocket": ...
|
|
109
|
+
@overload
|
|
110
|
+
def __matmul__(self, other: "CombineTransform") -> "VectorSocket": ...
|
|
111
|
+
def __matmul__(
|
|
112
|
+
self, other: "Position | CombineTransform | VectorSocket | MatrixSocket"
|
|
113
|
+
) -> "VectorSocket | MatrixSocket":
|
|
114
|
+
from ..builder.socket import VectorSocket
|
|
115
|
+
from ..nodes.geometry import (
|
|
116
|
+
MultiplyMatrices,
|
|
117
|
+
Position,
|
|
118
|
+
TransformPoint,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if isinstance(other, (Position, VectorSocket)):
|
|
122
|
+
return TransformPoint(other, self).o.vector # ty: ignore[invalid-argument-type]
|
|
123
|
+
|
|
124
|
+
return MultiplyMatrices(self, other).o.matrix # ty: ignore[invalid-argument-type]
|
|
125
|
+
|
|
126
|
+
def __rmatmul__(self, other: Any) -> "MatrixSocket | VectorSocket":
|
|
127
|
+
from ..builder.socket import VectorSocket
|
|
128
|
+
from ..nodes.geometry import MultiplyMatrices, Position, TransformPoint
|
|
129
|
+
|
|
130
|
+
if isinstance(
|
|
131
|
+
self,
|
|
132
|
+
(
|
|
133
|
+
VectorSocket,
|
|
134
|
+
Position,
|
|
135
|
+
),
|
|
136
|
+
):
|
|
137
|
+
return TransformPoint(self, other).o.vector
|
|
138
|
+
|
|
139
|
+
return MultiplyMatrices(other, self).o.matrix # ty: ignore[invalid-argument-type]
|
|
104
140
|
|
|
105
141
|
def __neg__(self) -> "FloatSocket | VectorSocket | IntegerSocket":
|
|
106
|
-
return
|
|
142
|
+
return _wrap_socket(self._default_output_socket)._dispatch_unary("negate")
|
|
107
143
|
|
|
108
144
|
def __abs__(self) -> "FloatSocket | VectorSocket | IntegerSocket":
|
|
109
|
-
return
|
|
110
|
-
|
|
111
|
-
|
|
145
|
+
return _wrap_socket(self._default_output_socket)._dispatch_unary("absolute")
|
|
146
|
+
|
|
147
|
+
if TYPE_CHECKING:
|
|
148
|
+
|
|
149
|
+
def __mul__(self, other: Any) -> Self: ...
|
|
150
|
+
def __rmul__(self, other: Any) -> Self: ...
|
|
151
|
+
def __truediv__(self, other: Any) -> Self: ...
|
|
152
|
+
def __rtruediv__(self, other: Any) -> Self: ...
|
|
153
|
+
def __add__(self, other: Any) -> Self: ...
|
|
154
|
+
def __radd__(self, other: Any) -> Self: ...
|
|
155
|
+
def __sub__(self, other: Any) -> Self: ...
|
|
156
|
+
def __rsub__(self, other: Any) -> Self: ...
|
|
157
|
+
def __pow__(self, other: Any) -> Self: ...
|
|
158
|
+
def __rpow__(self, other: Any) -> Self: ...
|
|
159
|
+
def __mod__(self, other: Any) -> Self: ...
|
|
160
|
+
def __rmod__(self, other: Any) -> Self: ...
|
|
161
|
+
def __floordiv__(self, other: Any) -> Self: ...
|
|
162
|
+
def __rfloordiv__(self, other: Any) -> Self: ...
|
|
163
|
+
def __neg__(self) -> Self: ...
|
|
164
|
+
def __abs__(self) -> Self: ...
|
|
112
165
|
|
|
113
166
|
def _apply_compare_operation(
|
|
114
167
|
self, other: Any, operation: str
|
|
@@ -118,7 +171,7 @@ class OperatorMixin:
|
|
|
118
171
|
other,
|
|
119
172
|
False,
|
|
120
173
|
)
|
|
121
|
-
return
|
|
174
|
+
return _wrap_socket(socket)._dispatch_compare(other, operation)
|
|
122
175
|
|
|
123
176
|
def __lt__(self, other: Any) -> "FloatSocket | BooleanSocket":
|
|
124
177
|
return self._apply_compare_operation(other, "less_than")
|
|
@@ -172,41 +225,6 @@ class OperatorMixin:
|
|
|
172
225
|
|
|
173
226
|
return BooleanMath.l_not(cast(Any, self))
|
|
174
227
|
|
|
175
|
-
@staticmethod
|
|
176
|
-
def _cast_to_matrix(value) -> MatrixSocket:
|
|
177
|
-
from ..nodes.geometry.converter import CombineMatrix
|
|
178
|
-
|
|
179
|
-
if hasattr(value, "shape") and value.shape == (4, 4):
|
|
180
|
-
return CombineMatrix(*value.ravel()).o.matrix
|
|
181
|
-
else:
|
|
182
|
-
return value
|
|
183
|
-
|
|
184
|
-
def __matmul__(self, other: Any) -> "MatrixSocket | VectorSocket":
|
|
185
|
-
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
186
|
-
|
|
187
|
-
other = self._cast_to_matrix(other)
|
|
188
|
-
socket = self._default_output_socket
|
|
189
|
-
|
|
190
|
-
if socket.type == "MATRIX" and other.type == "VECTOR":
|
|
191
|
-
return TransformPoint(other, socket).o.vector
|
|
192
|
-
|
|
193
|
-
return MultiplyMatrices(socket, other).o.matrix
|
|
194
|
-
|
|
195
|
-
@overload
|
|
196
|
-
def __rmatmul__(self, other: MatrixSocket) -> "MatrixSocket": ...
|
|
197
|
-
@overload
|
|
198
|
-
def __rmatmul__(self, other: VectorSocket) -> "VectorSocket": ...
|
|
199
|
-
def __rmatmul__(self, other: Any) -> "MatrixSocket | VectorSocket":
|
|
200
|
-
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
201
|
-
|
|
202
|
-
other = self._cast_to_matrix(other)
|
|
203
|
-
socket = self._default_output_socket
|
|
204
|
-
|
|
205
|
-
if socket.type == "VECTOR" and getattr(other, "type", None) == "MATRIX":
|
|
206
|
-
return TransformPoint(socket, other).o.vector
|
|
207
|
-
|
|
208
|
-
return MultiplyMatrices(other, socket).o.matrix
|
|
209
|
-
|
|
210
228
|
|
|
211
229
|
class LinkingMixin:
|
|
212
230
|
"""Node/socket linking logic: ``>>``, ``_link``, best-socket matching.
|
|
@@ -332,11 +350,10 @@ class LinkingMixin:
|
|
|
332
350
|
source: "InputLinkable",
|
|
333
351
|
input: "InputLinkable | str",
|
|
334
352
|
):
|
|
353
|
+
from .node import _find_socket_from_name
|
|
354
|
+
|
|
335
355
|
if isinstance(input, str):
|
|
336
|
-
|
|
337
|
-
self._link(source, self.node.inputs[input])
|
|
338
|
-
except KeyError:
|
|
339
|
-
self._link(source, self.node.inputs[self.i._index(input)])
|
|
356
|
+
self._link(source, _find_socket_from_name(self.node.inputs, input))
|
|
340
357
|
else:
|
|
341
358
|
self._link(source, input)
|
|
342
359
|
|
|
@@ -45,6 +45,25 @@ if TYPE_CHECKING:
|
|
|
45
45
|
def i(self) -> SocketAccessor: ...
|
|
46
46
|
|
|
47
47
|
|
|
48
|
+
def _find_socket_from_name(
|
|
49
|
+
collection: bpy.types.NodeInputs | bpy.types.NodeOutputs | list[NodeSocket],
|
|
50
|
+
name: str,
|
|
51
|
+
) -> NodeSocket:
|
|
52
|
+
ids = [socket.identifier for socket in collection]
|
|
53
|
+
names = [socket.name for socket in collection]
|
|
54
|
+
for format in [name, name.title(), name.replace("_", " ").title()]:
|
|
55
|
+
try:
|
|
56
|
+
return collection[names.index(format)]
|
|
57
|
+
except ValueError:
|
|
58
|
+
try:
|
|
59
|
+
return collection[ids.index(format)]
|
|
60
|
+
except ValueError:
|
|
61
|
+
continue
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Socket '{name}' not found in collection names or ids, available names: {names}, available ids: {ids}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
48
67
|
class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
49
68
|
"""Base class for all node wrappers."""
|
|
50
69
|
|
|
@@ -143,8 +162,8 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
143
162
|
input.default_value = value # type: ignore
|
|
144
163
|
|
|
145
164
|
def _establish_links(self, **kwargs: InputAny):
|
|
146
|
-
input_ids = [input.identifier for input in self.node.inputs]
|
|
147
165
|
for name, value in kwargs.items():
|
|
166
|
+
# TODO: don't like these manual overrides for particular nodes, but best I can do for now
|
|
148
167
|
if value is None or (
|
|
149
168
|
"GridPrune" in self._bl_idname
|
|
150
169
|
and name == "Threshold"
|
|
@@ -167,15 +186,13 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
167
186
|
elif isinstance(value, _NodeLike):
|
|
168
187
|
self._link_from(value.o._best_match(self.i._get(name).type), name) # type: ignore
|
|
169
188
|
else:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
input = self.node.inputs[name.replace("_", " ").title()]
|
|
178
|
-
self._set_input_default_value(input, value)
|
|
189
|
+
# TODO: explicitly skipping the sockets for BooleanMath as they are default false,
|
|
190
|
+
# but this needs to be a more generic solution for sockets which aren't available
|
|
191
|
+
# https://github.com/BradyAJohnston/nodebpy/issues/90
|
|
192
|
+
if "BooleanMath" in self._bl_idname and value is False:
|
|
193
|
+
continue
|
|
194
|
+
socket = _find_socket_from_name(self.node.inputs, name)
|
|
195
|
+
self._set_input_default_value(socket, value)
|
|
179
196
|
|
|
180
197
|
@property
|
|
181
198
|
def o(self) -> SocketAccessor:
|