nodebpy 0.15.1__tar.gz → 0.16.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.15.1 → nodebpy-0.16.0}/PKG-INFO +1 -1
- {nodebpy-0.15.1 → nodebpy-0.16.0}/pyproject.toml +2 -1
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/accessor.py +13 -2
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/mixins.py +42 -29
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/node.py +6 -4
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/socket.py +538 -333
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/tree.py +1 -1
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/manual.py +6 -2
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/attribute.py +2 -1
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/groups.py +5 -9
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/manual.py +7 -70
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/manual.py +2 -2
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/types.py +1 -1
- {nodebpy-0.15.1 → nodebpy-0.16.0}/README.md +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/arrange.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/_registry.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/builder/_utils.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/diagram.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/config.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/lib/nodearrange/utils.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/color.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/converter.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/distort.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/filter.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/group.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/input.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/interface.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/matte.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/output.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/compositor/vector.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/color.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/converter.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/geometry.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/grid.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/group.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/input.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/interface.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/output.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/texture.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/utilities.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/vector.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/geometry/zone.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/__init__.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/color.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/converter.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/grid.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/group.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/input.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/output.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/script.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/shader.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/texture.py +0 -0
- {nodebpy-0.15.1 → nodebpy-0.16.0}/src/nodebpy/nodes/shader/vector.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nodebpy"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.16.0"
|
|
4
4
|
description = "Build nodes trees in Blender more elegantly with code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -38,4 +38,5 @@ dev = [
|
|
|
38
38
|
"syrupy>=5.0.0",
|
|
39
39
|
"tree-clipper>=0.1.1",
|
|
40
40
|
"pytest-xdist>=3.8.0",
|
|
41
|
+
"griffe<2.0.0"
|
|
41
42
|
]
|
|
@@ -14,6 +14,7 @@ from ._utils import (
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
+
from .node import BaseNode
|
|
17
18
|
from .socket import Socket
|
|
18
19
|
|
|
19
20
|
|
|
@@ -30,9 +31,12 @@ class SocketAccessor:
|
|
|
30
31
|
self,
|
|
31
32
|
collection: bpy.types.NodeInputs | bpy.types.NodeOutputs | list[NodeSocket],
|
|
32
33
|
direction: Literal["input", "output"],
|
|
34
|
+
*,
|
|
35
|
+
builder: BaseNode | None = None,
|
|
33
36
|
):
|
|
34
37
|
self._direction = direction
|
|
35
38
|
self._collection = collection
|
|
39
|
+
self._builder = builder
|
|
36
40
|
|
|
37
41
|
def _index(self, key: str | int) -> int:
|
|
38
42
|
"""Find socket index by identifier, falling back to name.
|
|
@@ -74,11 +78,18 @@ class SocketAccessor:
|
|
|
74
78
|
def _get(self, key: str | int | slice) -> "Socket | list[Socket]":
|
|
75
79
|
"""Get a Socket for a socket by identifier, name, or index."""
|
|
76
80
|
if isinstance(key, slice):
|
|
77
|
-
|
|
81
|
+
sockets = [
|
|
78
82
|
_get_socket_linker(self._collection[i])
|
|
79
83
|
for i in range(*key.indices(len(self._collection)))
|
|
80
84
|
]
|
|
81
|
-
|
|
85
|
+
if self._builder is not None:
|
|
86
|
+
for s in sockets:
|
|
87
|
+
s._builder_node = self._builder
|
|
88
|
+
return sockets
|
|
89
|
+
socket = _get_socket_linker(self._collection[self._index(key)])
|
|
90
|
+
if self._builder is not None:
|
|
91
|
+
socket._builder_node = self._builder
|
|
92
|
+
return socket
|
|
82
93
|
|
|
83
94
|
@overload
|
|
84
95
|
def __getitem__(self, key: slice) -> "list[Socket]": ...
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from types import EllipsisType
|
|
4
|
-
from typing import TYPE_CHECKING, Any, TypeVar
|
|
4
|
+
from typing import TYPE_CHECKING, Any, TypeVar, overload
|
|
5
5
|
|
|
6
6
|
from bpy.types import NodeLink, NodeSocket
|
|
7
7
|
|
|
@@ -14,7 +14,14 @@ if TYPE_CHECKING:
|
|
|
14
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
|
|
17
|
+
from .socket import (
|
|
18
|
+
BooleanSocket,
|
|
19
|
+
FloatSocket,
|
|
20
|
+
IntegerSocket,
|
|
21
|
+
MatrixSocket,
|
|
22
|
+
Socket,
|
|
23
|
+
VectorSocket,
|
|
24
|
+
)
|
|
18
25
|
from .tree import TreeBuilder
|
|
19
26
|
|
|
20
27
|
|
|
@@ -30,7 +37,7 @@ class OperatorMixin:
|
|
|
30
37
|
|
|
31
38
|
def _apply_math_operation(
|
|
32
39
|
self, other: Any, operation: str, reverse: bool = False
|
|
33
|
-
) -> "
|
|
40
|
+
) -> "FloatSocket | VectorSocket | IntegerSocket":
|
|
34
41
|
socket, other, reverse = _resolve_promotion(
|
|
35
42
|
self._default_output_socket,
|
|
36
43
|
other,
|
|
@@ -38,43 +45,43 @@ class OperatorMixin:
|
|
|
38
45
|
)
|
|
39
46
|
return _get_socket_linker(socket)._dispatch_math(other, operation, reverse)
|
|
40
47
|
|
|
41
|
-
def __mul__(self, other: Any) -> "
|
|
48
|
+
def __mul__(self, other: Any) -> "FloatSocket":
|
|
42
49
|
return self._apply_math_operation(other, "multiply")
|
|
43
50
|
|
|
44
|
-
def __rmul__(self, other: Any) -> "
|
|
51
|
+
def __rmul__(self, other: Any) -> "FloatSocket":
|
|
45
52
|
return self._apply_math_operation(other, "multiply", reverse=True)
|
|
46
53
|
|
|
47
|
-
def __truediv__(self, other: Any) -> "
|
|
54
|
+
def __truediv__(self, other: Any) -> "FloatSocket":
|
|
48
55
|
return self._apply_math_operation(other, "divide")
|
|
49
56
|
|
|
50
|
-
def __rtruediv__(self, other: Any) -> "
|
|
57
|
+
def __rtruediv__(self, other: Any) -> "FloatSocket":
|
|
51
58
|
return self._apply_math_operation(other, "divide", reverse=True)
|
|
52
59
|
|
|
53
|
-
def __add__(self, other: Any) -> "
|
|
60
|
+
def __add__(self, other: Any) -> "FloatSocket":
|
|
54
61
|
return self._apply_math_operation(other, "add")
|
|
55
62
|
|
|
56
|
-
def __radd__(self, other: Any) -> "
|
|
63
|
+
def __radd__(self, other: Any) -> "FloatSocket":
|
|
57
64
|
return self._apply_math_operation(other, "add", reverse=True)
|
|
58
65
|
|
|
59
|
-
def __sub__(self, other: Any) -> "
|
|
66
|
+
def __sub__(self, other: Any) -> "FloatSocket":
|
|
60
67
|
return self._apply_math_operation(other, "subtract")
|
|
61
68
|
|
|
62
|
-
def __rsub__(self, other: Any) -> "
|
|
69
|
+
def __rsub__(self, other: Any) -> "FloatSocket":
|
|
63
70
|
return self._apply_math_operation(other, "subtract", reverse=True)
|
|
64
71
|
|
|
65
|
-
def __pow__(self, other: Any) -> "
|
|
72
|
+
def __pow__(self, other: Any) -> "FloatSocket":
|
|
66
73
|
return self._apply_math_operation(other, "power")
|
|
67
74
|
|
|
68
|
-
def __rpow__(self, other: Any) -> "
|
|
75
|
+
def __rpow__(self, other: Any) -> "FloatSocket":
|
|
69
76
|
return self._apply_math_operation(other, "power", reverse=True)
|
|
70
77
|
|
|
71
|
-
def __mod__(self, other: Any) -> "
|
|
78
|
+
def __mod__(self, other: Any) -> "FloatSocket":
|
|
72
79
|
return self._apply_math_operation(other, "modulo")
|
|
73
80
|
|
|
74
|
-
def __rmod__(self, other: Any) -> "
|
|
81
|
+
def __rmod__(self, other: Any) -> "FloatSocket":
|
|
75
82
|
return self._apply_math_operation(other, "modulo", reverse=True)
|
|
76
83
|
|
|
77
|
-
def __floordiv__(self, other: Any) -> "
|
|
84
|
+
def __floordiv__(self, other: Any) -> "FloatSocket":
|
|
78
85
|
socket, other, reverse = _resolve_promotion(
|
|
79
86
|
self._default_output_socket,
|
|
80
87
|
other,
|
|
@@ -82,7 +89,7 @@ class OperatorMixin:
|
|
|
82
89
|
)
|
|
83
90
|
return _get_socket_linker(socket)._dispatch_floordiv(other, reverse)
|
|
84
91
|
|
|
85
|
-
def __rfloordiv__(self, other: Any) -> "
|
|
92
|
+
def __rfloordiv__(self, other: Any) -> "FloatSocket":
|
|
86
93
|
socket, other, reverse = _resolve_promotion(
|
|
87
94
|
self._default_output_socket,
|
|
88
95
|
other,
|
|
@@ -90,17 +97,19 @@ class OperatorMixin:
|
|
|
90
97
|
)
|
|
91
98
|
return _get_socket_linker(socket)._dispatch_floordiv(other, reverse)
|
|
92
99
|
|
|
93
|
-
def __neg__(self) -> "
|
|
100
|
+
def __neg__(self) -> "FloatSocket":
|
|
94
101
|
return _get_socket_linker(self._default_output_socket)._dispatch_unary( # type: ignore[attr-defined]
|
|
95
102
|
"negate"
|
|
96
103
|
)
|
|
97
104
|
|
|
98
|
-
def __abs__(self) -> "
|
|
105
|
+
def __abs__(self) -> "FloatSocket":
|
|
99
106
|
return _get_socket_linker(self._default_output_socket)._dispatch_unary( # type: ignore[attr-defined]
|
|
100
107
|
"absolute"
|
|
101
108
|
)
|
|
102
109
|
|
|
103
|
-
def _apply_compare_operation(
|
|
110
|
+
def _apply_compare_operation(
|
|
111
|
+
self, other: Any, operation: str
|
|
112
|
+
) -> "FloatSocket | BooleanSocket":
|
|
104
113
|
socket, other, _ = _resolve_promotion(
|
|
105
114
|
self._default_output_socket, # type: ignore[attr-defined]
|
|
106
115
|
other,
|
|
@@ -108,7 +117,7 @@ class OperatorMixin:
|
|
|
108
117
|
)
|
|
109
118
|
return _get_socket_linker(socket)._dispatch_compare(other, operation)
|
|
110
119
|
|
|
111
|
-
def __lt__(self, other: Any) -> "
|
|
120
|
+
def __lt__(self, other: Any) -> "BooleanSocket":
|
|
112
121
|
return self._apply_compare_operation(other, "less_than")
|
|
113
122
|
|
|
114
123
|
def __gt__(self, other: Any) -> "Compare":
|
|
@@ -169,27 +178,31 @@ class OperatorMixin:
|
|
|
169
178
|
else:
|
|
170
179
|
return value
|
|
171
180
|
|
|
172
|
-
def __matmul__(self, other: Any) -> "
|
|
181
|
+
def __matmul__(self, other: Any) -> "MatrixSocket | VectorSocket":
|
|
173
182
|
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
174
183
|
|
|
175
184
|
other = self._cast_to_matrix(other)
|
|
176
185
|
socket = self._default_output_socket
|
|
177
186
|
|
|
178
187
|
if socket.type == "MATRIX" and other.type == "VECTOR":
|
|
179
|
-
return TransformPoint(other, socket)
|
|
188
|
+
return TransformPoint(other, socket).o.vector
|
|
180
189
|
|
|
181
|
-
return MultiplyMatrices(socket, other)
|
|
190
|
+
return MultiplyMatrices(socket, other).o.matrix
|
|
182
191
|
|
|
183
|
-
|
|
192
|
+
@overload
|
|
193
|
+
def __rmatmul__(self, other: MatrixSocket) -> "MatrixSocket": ...
|
|
194
|
+
@overload
|
|
195
|
+
def __rmatmul__(self, other: VectorSocket) -> "VectorSocket": ...
|
|
196
|
+
def __rmatmul__(self, other: Any) -> "MatrixSocket | VectorSocket":
|
|
184
197
|
from ..nodes.geometry.converter import MultiplyMatrices, TransformPoint
|
|
185
198
|
|
|
186
199
|
other = self._cast_to_matrix(other)
|
|
187
200
|
socket = self._default_output_socket
|
|
188
201
|
|
|
189
202
|
if socket.type == "VECTOR" and getattr(other, "type", None) == "MATRIX":
|
|
190
|
-
return TransformPoint(socket, other)
|
|
203
|
+
return TransformPoint(socket, other).o.vector
|
|
191
204
|
|
|
192
|
-
return MultiplyMatrices(other, socket)
|
|
205
|
+
return MultiplyMatrices(other, socket).o.matrix
|
|
193
206
|
|
|
194
207
|
|
|
195
208
|
class LinkingMixin:
|
|
@@ -202,7 +215,7 @@ class LinkingMixin:
|
|
|
202
215
|
tree: "TreeBuilder"
|
|
203
216
|
|
|
204
217
|
def _source_socket(self, node: "InputLinkable | Socket | NodeSocket") -> NodeSocket:
|
|
205
|
-
assert node
|
|
218
|
+
assert node is not None
|
|
206
219
|
if isinstance(node, NodeSocket):
|
|
207
220
|
return node
|
|
208
221
|
elif hasattr(node, "_default_output_socket"):
|
|
@@ -211,7 +224,7 @@ class LinkingMixin:
|
|
|
211
224
|
raise TypeError(f"Unsupported type: {type(node)}")
|
|
212
225
|
|
|
213
226
|
def _target_socket(self, node: "InputLinkable | Socket | NodeSocket") -> NodeSocket:
|
|
214
|
-
assert node
|
|
227
|
+
assert node is not None
|
|
215
228
|
if isinstance(node, NodeSocket):
|
|
216
229
|
return node
|
|
217
230
|
elif hasattr(node, "_default_input_socket"):
|
|
@@ -21,6 +21,7 @@ from bpy.types import (
|
|
|
21
21
|
GeometryNodeTree,
|
|
22
22
|
Node,
|
|
23
23
|
NodeSocket,
|
|
24
|
+
NodeTree,
|
|
24
25
|
ShaderNodeGroup,
|
|
25
26
|
ShaderNodeTree,
|
|
26
27
|
)
|
|
@@ -101,8 +102,9 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
101
102
|
|
|
102
103
|
@classmethod
|
|
103
104
|
def _from_node(cls, node: Node) -> Self:
|
|
104
|
-
builder = cls()
|
|
105
|
-
builder.
|
|
105
|
+
builder = cls.__new__(cls)
|
|
106
|
+
builder._tree = TreeBuilder(cast(NodeTree, node.id_data))
|
|
107
|
+
builder._placeholder_inputs = []
|
|
106
108
|
builder.node = node
|
|
107
109
|
return builder
|
|
108
110
|
|
|
@@ -178,12 +180,12 @@ class BaseNode(_NodeLike, OperatorMixin, LinkingMixin):
|
|
|
178
180
|
@property
|
|
179
181
|
def o(self) -> SocketAccessor:
|
|
180
182
|
"""Output socket accessor. Subclasses narrow the return type via TYPE_CHECKING."""
|
|
181
|
-
return SocketAccessor(self.node.outputs, "output")
|
|
183
|
+
return SocketAccessor(self.node.outputs, "output", builder=self)
|
|
182
184
|
|
|
183
185
|
@property
|
|
184
186
|
def i(self) -> SocketAccessor:
|
|
185
187
|
"""Input socket accessor. Subclasses narrow the return type via TYPE_CHECKING."""
|
|
186
|
-
return SocketAccessor(self.node.inputs, "input")
|
|
188
|
+
return SocketAccessor(self.node.inputs, "input", builder=self)
|
|
187
189
|
|
|
188
190
|
|
|
189
191
|
class DynamicInputsMixin(ABC):
|