nodebpy 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
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/builder.py +19 -13
- nodebpy/nodes/__init__.py +352 -335
- nodebpy/nodes/attribute.py +362 -307
- nodebpy/nodes/color.py +30 -34
- nodebpy/nodes/converter.py +1987 -2978
- nodebpy/nodes/experimental.py +201 -203
- nodebpy/nodes/geometry.py +4189 -3644
- nodebpy/nodes/grid.py +932 -447
- nodebpy/nodes/group.py +7 -10
- nodebpy/nodes/input.py +1496 -1308
- nodebpy/nodes/interface.py +236 -117
- nodebpy/nodes/manual.py +2022 -0
- nodebpy/nodes/output.py +85 -0
- nodebpy/nodes/texture.py +867 -7
- nodebpy/nodes/vector.py +528 -0
- nodebpy/nodes/zone.py +7 -7
- nodebpy/{nodes/types.py → types.py} +14 -1
- {nodebpy-0.2.0.dist-info → nodebpy-0.2.1.dist-info}/METADATA +2 -2
- nodebpy-0.2.1.dist-info/RECORD +26 -0
- nodebpy/nodes/mesh.py +0 -17
- nodebpy-0.2.0.dist-info/RECORD +0 -25
- {nodebpy-0.2.0.dist-info → nodebpy-0.2.1.dist-info}/WHEEL +0 -0
- {nodebpy-0.2.0.dist-info → nodebpy-0.2.1.dist-info}/entry_points.txt +0 -0
nodebpy/nodes/attribute.py
CHANGED
|
@@ -3,114 +3,128 @@ from typing import Literal
|
|
|
3
3
|
import bpy
|
|
4
4
|
|
|
5
5
|
from ..builder import NodeBuilder, SocketLinker
|
|
6
|
-
from
|
|
7
|
-
LINKABLE,
|
|
6
|
+
from ..types import (
|
|
8
7
|
TYPE_INPUT_BOOLEAN,
|
|
9
8
|
TYPE_INPUT_GEOMETRY,
|
|
10
9
|
TYPE_INPUT_INT,
|
|
11
10
|
TYPE_INPUT_MENU,
|
|
12
11
|
TYPE_INPUT_STRING,
|
|
12
|
+
TYPE_INPUT_ROTATION,
|
|
13
|
+
TYPE_INPUT_COLOR,
|
|
13
14
|
TYPE_INPUT_VALUE,
|
|
14
|
-
|
|
15
|
-
_AttributeDomains,
|
|
16
|
-
_StoreNamedAttributeTypes,
|
|
15
|
+
TYPE_INPUT_VECTOR,
|
|
17
16
|
)
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
class
|
|
21
|
-
"""
|
|
19
|
+
class BlurAttribute(NodeBuilder):
|
|
20
|
+
"""Mix attribute values of neighboring elements"""
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
node: bpy.types.
|
|
22
|
+
_bl_idname = "GeometryNodeBlurAttribute"
|
|
23
|
+
node: bpy.types.GeometryNodeBlurAttribute
|
|
25
24
|
|
|
26
25
|
def __init__(
|
|
27
26
|
self,
|
|
28
|
-
|
|
27
|
+
value: TYPE_INPUT_VALUE = 0.0,
|
|
28
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
29
|
+
weight: TYPE_INPUT_VALUE = 1.0,
|
|
29
30
|
*,
|
|
30
|
-
|
|
31
|
-
"MESH", "POINTCLOUD", "CURVE", "INSTANCES", "GREASEPENCIL"
|
|
32
|
-
] = "MESH",
|
|
31
|
+
data_type: Literal["FLOAT", "INT", "FLOAT_VECTOR", "FLOAT_COLOR"] = "FLOAT",
|
|
33
32
|
):
|
|
34
33
|
super().__init__()
|
|
35
|
-
key_args = {"
|
|
36
|
-
self.
|
|
34
|
+
key_args = {"Value": value, "Iterations": iterations, "Weight": weight}
|
|
35
|
+
self.data_type = data_type
|
|
37
36
|
self._establish_links(**key_args)
|
|
38
37
|
|
|
39
|
-
@
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
@classmethod
|
|
39
|
+
def float(
|
|
40
|
+
cls,
|
|
41
|
+
value: TYPE_INPUT_VALUE = 0.0,
|
|
42
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
43
|
+
weight: TYPE_INPUT_VALUE = 1.0,
|
|
44
|
+
) -> "BlurAttribute":
|
|
45
|
+
"""Create Blur Attribute with operation 'Float'."""
|
|
46
|
+
return cls(data_type="FLOAT", value=value, iterations=iterations, weight=weight)
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def integer(
|
|
50
|
+
cls,
|
|
51
|
+
value: TYPE_INPUT_INT = 0,
|
|
52
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
53
|
+
weight: TYPE_INPUT_VALUE = 1.0,
|
|
54
|
+
) -> "BlurAttribute":
|
|
55
|
+
"""Create Blur Attribute with operation 'Integer'."""
|
|
56
|
+
return cls(data_type="INT", value=value, iterations=iterations, weight=weight)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def vector(
|
|
60
|
+
cls,
|
|
61
|
+
value: TYPE_INPUT_VECTOR = None,
|
|
62
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
63
|
+
weight: TYPE_INPUT_VALUE = 1.0,
|
|
64
|
+
) -> "BlurAttribute":
|
|
65
|
+
"""Create Blur Attribute with operation 'Vector'."""
|
|
66
|
+
return cls(
|
|
67
|
+
data_type="FLOAT_VECTOR", value=value, iterations=iterations, weight=weight
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def color(
|
|
72
|
+
cls,
|
|
73
|
+
value: TYPE_INPUT_COLOR = None,
|
|
74
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
75
|
+
weight: TYPE_INPUT_VALUE = 1.0,
|
|
76
|
+
) -> "BlurAttribute":
|
|
77
|
+
"""Create Blur Attribute with operation 'Color'."""
|
|
78
|
+
return cls(
|
|
79
|
+
data_type="FLOAT_COLOR", value=value, iterations=iterations, weight=weight
|
|
80
|
+
)
|
|
43
81
|
|
|
44
82
|
@property
|
|
45
|
-
def
|
|
46
|
-
"""
|
|
47
|
-
return self.
|
|
83
|
+
def i_value(self) -> SocketLinker:
|
|
84
|
+
"""Input socket: Value"""
|
|
85
|
+
return self._input("Value")
|
|
48
86
|
|
|
49
87
|
@property
|
|
50
|
-
def
|
|
51
|
-
"""
|
|
52
|
-
return self.
|
|
88
|
+
def i_iterations(self) -> SocketLinker:
|
|
89
|
+
"""Input socket: Iterations"""
|
|
90
|
+
return self._input("Iterations")
|
|
53
91
|
|
|
54
92
|
@property
|
|
55
|
-
def
|
|
56
|
-
"""
|
|
57
|
-
return self.
|
|
93
|
+
def i_weight(self) -> SocketLinker:
|
|
94
|
+
"""Input socket: Weight"""
|
|
95
|
+
return self._input("Weight")
|
|
58
96
|
|
|
59
97
|
@property
|
|
60
|
-
def
|
|
61
|
-
"""Output socket:
|
|
62
|
-
return self._output("
|
|
98
|
+
def o_value(self) -> SocketLinker:
|
|
99
|
+
"""Output socket: Value"""
|
|
100
|
+
return self._output("Value")
|
|
63
101
|
|
|
64
102
|
@property
|
|
65
|
-
def
|
|
66
|
-
self
|
|
67
|
-
) -> Literal["MESH", "POINTCLOUD", "CURVE", "INSTANCES", "GREASEPENCIL"]:
|
|
68
|
-
return self.node.component
|
|
103
|
+
def data_type(self) -> Literal["FLOAT", "INT", "FLOAT_VECTOR", "FLOAT_COLOR"]:
|
|
104
|
+
return self.node.data_type
|
|
69
105
|
|
|
70
|
-
@
|
|
71
|
-
def
|
|
72
|
-
self
|
|
73
|
-
):
|
|
74
|
-
match value:
|
|
75
|
-
case "MESH" | "POINTCLOUD" | "CURVE":
|
|
76
|
-
self._default_output_id = "Point Count"
|
|
77
|
-
case "INSTANCES":
|
|
78
|
-
self._default_output_id = "Instance Count"
|
|
79
|
-
case "GREASEPENCIL":
|
|
80
|
-
self._default_output_id = "Layer Count"
|
|
81
|
-
self.node.component = value
|
|
106
|
+
@data_type.setter
|
|
107
|
+
def data_type(self, value: Literal["FLOAT", "INT", "FLOAT_VECTOR", "FLOAT_COLOR"]):
|
|
108
|
+
self.node.data_type = value
|
|
82
109
|
|
|
83
110
|
|
|
84
|
-
class
|
|
85
|
-
"""
|
|
111
|
+
class DomainSize(NodeBuilder):
|
|
112
|
+
"""Retrieve the number of elements in a geometry for each attribute domain"""
|
|
86
113
|
|
|
87
|
-
|
|
88
|
-
node: bpy.types.
|
|
114
|
+
_bl_idname = "GeometryNodeAttributeDomainSize"
|
|
115
|
+
node: bpy.types.GeometryNodeAttributeDomainSize
|
|
89
116
|
|
|
90
117
|
def __init__(
|
|
91
118
|
self,
|
|
92
119
|
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
93
|
-
selection: TYPE_INPUT_BOOLEAN = True,
|
|
94
|
-
attribute: LINKABLE = None,
|
|
95
120
|
*,
|
|
96
|
-
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
] = "FLOAT",
|
|
100
|
-
domain: Literal[
|
|
101
|
-
"POINT", "EDGE", "FACE", "CORNER", "CURVE", "INSTANCE", "LAYER"
|
|
102
|
-
] = "POINT",
|
|
103
|
-
**kwargs,
|
|
121
|
+
component: Literal[
|
|
122
|
+
"MESH", "POINTCLOUD", "CURVE", "INSTANCES", "GREASEPENCIL"
|
|
123
|
+
] = "MESH",
|
|
104
124
|
):
|
|
105
125
|
super().__init__()
|
|
106
|
-
key_args = {
|
|
107
|
-
|
|
108
|
-
"Selection": selection,
|
|
109
|
-
"Attribute": attribute,
|
|
110
|
-
}
|
|
111
|
-
key_args.update(kwargs)
|
|
112
|
-
self.data_type = data_type
|
|
113
|
-
self.domain = domain
|
|
126
|
+
key_args = {"Geometry": geometry}
|
|
127
|
+
self.component = component
|
|
114
128
|
self._establish_links(**key_args)
|
|
115
129
|
|
|
116
130
|
@property
|
|
@@ -119,170 +133,68 @@ class AttributeStatistic(NodeBuilder):
|
|
|
119
133
|
return self._input("Geometry")
|
|
120
134
|
|
|
121
135
|
@property
|
|
122
|
-
def
|
|
123
|
-
"""
|
|
124
|
-
return self.
|
|
125
|
-
|
|
126
|
-
@property
|
|
127
|
-
def i_attribute(self) -> SocketLinker:
|
|
128
|
-
"""Input socket: Attribute"""
|
|
129
|
-
return self._input("Attribute")
|
|
130
|
-
|
|
131
|
-
@property
|
|
132
|
-
def o_mean(self) -> SocketLinker:
|
|
133
|
-
"""Output socket: Mean"""
|
|
134
|
-
return self._output("Mean")
|
|
135
|
-
|
|
136
|
-
@property
|
|
137
|
-
def o_median(self) -> SocketLinker:
|
|
138
|
-
"""Output socket: Median"""
|
|
139
|
-
return self._output("Median")
|
|
140
|
-
|
|
141
|
-
@property
|
|
142
|
-
def o_sum(self) -> SocketLinker:
|
|
143
|
-
"""Output socket: Sum"""
|
|
144
|
-
return self._output("Sum")
|
|
145
|
-
|
|
146
|
-
@property
|
|
147
|
-
def o_min(self) -> SocketLinker:
|
|
148
|
-
"""Output socket: Min"""
|
|
149
|
-
return self._output("Min")
|
|
150
|
-
|
|
151
|
-
@property
|
|
152
|
-
def o_max(self) -> SocketLinker:
|
|
153
|
-
"""Output socket: Max"""
|
|
154
|
-
return self._output("Max")
|
|
155
|
-
|
|
156
|
-
@property
|
|
157
|
-
def o_range(self) -> SocketLinker:
|
|
158
|
-
"""Output socket: Range"""
|
|
159
|
-
return self._output("Range")
|
|
160
|
-
|
|
161
|
-
@property
|
|
162
|
-
def o_standard_deviation(self) -> SocketLinker:
|
|
163
|
-
"""Output socket: Standard Deviation"""
|
|
164
|
-
return self._output("Standard Deviation")
|
|
165
|
-
|
|
166
|
-
@property
|
|
167
|
-
def o_variance(self) -> SocketLinker:
|
|
168
|
-
"""Output socket: Variance"""
|
|
169
|
-
return self._output("Variance")
|
|
136
|
+
def o_point_count(self) -> SocketLinker:
|
|
137
|
+
"""Output socket: Point Count"""
|
|
138
|
+
return self._output("Point Count")
|
|
170
139
|
|
|
171
140
|
@property
|
|
172
|
-
def
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
"FLOAT",
|
|
176
|
-
"FLOAT_VECTOR",
|
|
177
|
-
]:
|
|
178
|
-
return self.node.data_type # type: ignore
|
|
179
|
-
|
|
180
|
-
@data_type.setter
|
|
181
|
-
def data_type(
|
|
182
|
-
self,
|
|
183
|
-
value: Literal[
|
|
184
|
-
"FLOAT",
|
|
185
|
-
"FLOAT_VECTOR",
|
|
186
|
-
],
|
|
187
|
-
):
|
|
188
|
-
self.node.data_type = value
|
|
141
|
+
def o_edge_count(self) -> SocketLinker:
|
|
142
|
+
"""Output socket: Edge Count"""
|
|
143
|
+
return self._output("Edge Count")
|
|
189
144
|
|
|
190
145
|
@property
|
|
191
|
-
def
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return self.node.domain
|
|
195
|
-
|
|
196
|
-
@domain.setter
|
|
197
|
-
def domain(
|
|
198
|
-
self,
|
|
199
|
-
value: _AttributeDomains,
|
|
200
|
-
):
|
|
201
|
-
self.node.domain = value
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
class BlurAttribute(NodeBuilder):
|
|
205
|
-
"""Mix attribute values of neighboring elements"""
|
|
206
|
-
|
|
207
|
-
name = "GeometryNodeBlurAttribute"
|
|
208
|
-
node: bpy.types.GeometryNodeBlurAttribute
|
|
209
|
-
|
|
210
|
-
def __init__(
|
|
211
|
-
self,
|
|
212
|
-
value: LINKABLE = None,
|
|
213
|
-
iterations: TYPE_INPUT_INT = 1,
|
|
214
|
-
weight: TYPE_INPUT_VALUE = 1.0,
|
|
215
|
-
*,
|
|
216
|
-
data_type: Literal[
|
|
217
|
-
"FLOAT",
|
|
218
|
-
"INT",
|
|
219
|
-
"FLOAT_VECTOR",
|
|
220
|
-
"FLOAT_COLOR",
|
|
221
|
-
] = "FLOAT",
|
|
222
|
-
):
|
|
223
|
-
super().__init__()
|
|
224
|
-
key_args = {"Value": value, "Iterations": iterations, "Weight": weight}
|
|
225
|
-
self.data_type = data_type
|
|
226
|
-
self._establish_links(**key_args)
|
|
146
|
+
def o_face_count(self) -> SocketLinker:
|
|
147
|
+
"""Output socket: Face Count"""
|
|
148
|
+
return self._output("Face Count")
|
|
227
149
|
|
|
228
150
|
@property
|
|
229
|
-
def
|
|
230
|
-
"""
|
|
231
|
-
return self.
|
|
151
|
+
def o_face_corner_count(self) -> SocketLinker:
|
|
152
|
+
"""Output socket: Face Corner Count"""
|
|
153
|
+
return self._output("Face Corner Count")
|
|
232
154
|
|
|
233
155
|
@property
|
|
234
|
-
def
|
|
235
|
-
"""
|
|
236
|
-
return self.
|
|
156
|
+
def o_spline_count(self) -> SocketLinker:
|
|
157
|
+
"""Output socket: Spline Count"""
|
|
158
|
+
return self._output("Spline Count")
|
|
237
159
|
|
|
238
160
|
@property
|
|
239
|
-
def
|
|
240
|
-
"""
|
|
241
|
-
return self.
|
|
161
|
+
def o_instance_count(self) -> SocketLinker:
|
|
162
|
+
"""Output socket: Instance Count"""
|
|
163
|
+
return self._output("Instance Count")
|
|
242
164
|
|
|
243
165
|
@property
|
|
244
|
-
def
|
|
245
|
-
"""Output socket:
|
|
246
|
-
return self._output("
|
|
166
|
+
def o_layer_count(self) -> SocketLinker:
|
|
167
|
+
"""Output socket: Layer Count"""
|
|
168
|
+
return self._output("Layer Count")
|
|
247
169
|
|
|
248
170
|
@property
|
|
249
|
-
def
|
|
171
|
+
def component(
|
|
250
172
|
self,
|
|
251
|
-
) -> Literal[
|
|
252
|
-
|
|
253
|
-
"INT",
|
|
254
|
-
"FLOAT_VECTOR",
|
|
255
|
-
"FLOAT_COLOR",
|
|
256
|
-
]:
|
|
257
|
-
return self.node.data_type # type: ignore
|
|
173
|
+
) -> Literal["MESH", "POINTCLOUD", "CURVE", "INSTANCES", "GREASEPENCIL"]:
|
|
174
|
+
return self.node.component
|
|
258
175
|
|
|
259
|
-
@
|
|
260
|
-
def
|
|
261
|
-
self,
|
|
262
|
-
value: Literal[
|
|
263
|
-
"FLOAT",
|
|
264
|
-
"INT",
|
|
265
|
-
"FLOAT_VECTOR",
|
|
266
|
-
"FLOAT_COLOR",
|
|
267
|
-
],
|
|
176
|
+
@component.setter
|
|
177
|
+
def component(
|
|
178
|
+
self, value: Literal["MESH", "POINTCLOUD", "CURVE", "INSTANCES", "GREASEPENCIL"]
|
|
268
179
|
):
|
|
269
|
-
self.node.
|
|
180
|
+
self.node.component = value
|
|
270
181
|
|
|
271
182
|
|
|
272
183
|
class RemoveNamedAttribute(NodeBuilder):
|
|
273
184
|
"""Delete an attribute with a specified name from a geometry. Typically used to optimize performance"""
|
|
274
185
|
|
|
275
|
-
|
|
186
|
+
_bl_idname = "GeometryNodeRemoveAttribute"
|
|
276
187
|
node: bpy.types.GeometryNodeRemoveAttribute
|
|
277
188
|
|
|
278
189
|
def __init__(
|
|
279
190
|
self,
|
|
280
191
|
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
281
|
-
pattern_mode:
|
|
192
|
+
pattern_mode: TYPE_INPUT_MENU = "Exact",
|
|
282
193
|
name: TYPE_INPUT_STRING = "",
|
|
283
194
|
):
|
|
284
195
|
super().__init__()
|
|
285
196
|
key_args = {"Geometry": geometry, "Pattern Mode": pattern_mode, "Name": name}
|
|
197
|
+
|
|
286
198
|
self._establish_links(**key_args)
|
|
287
199
|
|
|
288
200
|
@property
|
|
@@ -309,7 +221,7 @@ class RemoveNamedAttribute(NodeBuilder):
|
|
|
309
221
|
class StoreNamedAttribute(NodeBuilder):
|
|
310
222
|
"""Store the result of a field on a geometry as an attribute with the specified name"""
|
|
311
223
|
|
|
312
|
-
|
|
224
|
+
_bl_idname = "GeometryNodeStoreNamedAttribute"
|
|
313
225
|
node: bpy.types.GeometryNodeStoreNamedAttribute
|
|
314
226
|
|
|
315
227
|
def __init__(
|
|
@@ -317,10 +229,23 @@ class StoreNamedAttribute(NodeBuilder):
|
|
|
317
229
|
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
318
230
|
selection: TYPE_INPUT_BOOLEAN = True,
|
|
319
231
|
name: TYPE_INPUT_STRING = "",
|
|
320
|
-
value:
|
|
232
|
+
value: TYPE_INPUT_VALUE = 0.0,
|
|
321
233
|
*,
|
|
322
|
-
data_type:
|
|
323
|
-
|
|
234
|
+
data_type: Literal[
|
|
235
|
+
"FLOAT",
|
|
236
|
+
"INT",
|
|
237
|
+
"BOOLEAN",
|
|
238
|
+
"FLOAT_VECTOR",
|
|
239
|
+
"FLOAT_COLOR",
|
|
240
|
+
"QUATERNION",
|
|
241
|
+
"FLOAT4X4",
|
|
242
|
+
"INT8",
|
|
243
|
+
"FLOAT2",
|
|
244
|
+
"BYTE_COLOR",
|
|
245
|
+
] = "FLOAT",
|
|
246
|
+
domain: Literal[
|
|
247
|
+
"POINT", "EDGE", "FACE", "CORNER", "CURVE", "INSTANCE", "LAYER"
|
|
248
|
+
] = "POINT",
|
|
324
249
|
):
|
|
325
250
|
super().__init__()
|
|
326
251
|
key_args = {
|
|
@@ -333,6 +258,210 @@ class StoreNamedAttribute(NodeBuilder):
|
|
|
333
258
|
self.domain = domain
|
|
334
259
|
self._establish_links(**key_args)
|
|
335
260
|
|
|
261
|
+
@classmethod
|
|
262
|
+
def float(
|
|
263
|
+
cls,
|
|
264
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
265
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
266
|
+
name: TYPE_INPUT_STRING = "",
|
|
267
|
+
value: TYPE_INPUT_VALUE = 0.0,
|
|
268
|
+
) -> "StoreNamedAttribute":
|
|
269
|
+
"""Create Store Named Attribute with operation 'Float'."""
|
|
270
|
+
return cls(
|
|
271
|
+
data_type="FLOAT",
|
|
272
|
+
geometry=geometry,
|
|
273
|
+
selection=selection,
|
|
274
|
+
name=name,
|
|
275
|
+
value=value,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
@classmethod
|
|
279
|
+
def integer(
|
|
280
|
+
cls,
|
|
281
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
282
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
283
|
+
name: TYPE_INPUT_STRING = "",
|
|
284
|
+
value: TYPE_INPUT_INT = 0,
|
|
285
|
+
) -> "StoreNamedAttribute":
|
|
286
|
+
"""Create Store Named Attribute with operation 'Integer'."""
|
|
287
|
+
return cls(
|
|
288
|
+
data_type="INT",
|
|
289
|
+
geometry=geometry,
|
|
290
|
+
selection=selection,
|
|
291
|
+
name=name,
|
|
292
|
+
value=value,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
@classmethod
|
|
296
|
+
def boolean(
|
|
297
|
+
cls,
|
|
298
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
299
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
300
|
+
name: TYPE_INPUT_STRING = "",
|
|
301
|
+
value: TYPE_INPUT_BOOLEAN = False,
|
|
302
|
+
) -> "StoreNamedAttribute":
|
|
303
|
+
"""Create Store Named Attribute with operation 'Boolean'."""
|
|
304
|
+
return cls(
|
|
305
|
+
data_type="BOOLEAN",
|
|
306
|
+
geometry=geometry,
|
|
307
|
+
selection=selection,
|
|
308
|
+
name=name,
|
|
309
|
+
value=value,
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
@classmethod
|
|
313
|
+
def vector(
|
|
314
|
+
cls,
|
|
315
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
316
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
317
|
+
name: TYPE_INPUT_STRING = "",
|
|
318
|
+
value: TYPE_INPUT_VECTOR = None,
|
|
319
|
+
) -> "StoreNamedAttribute":
|
|
320
|
+
"""Create Store Named Attribute with operation 'Vector'."""
|
|
321
|
+
return cls(
|
|
322
|
+
data_type="FLOAT_VECTOR",
|
|
323
|
+
geometry=geometry,
|
|
324
|
+
selection=selection,
|
|
325
|
+
name=name,
|
|
326
|
+
value=value,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
@classmethod
|
|
330
|
+
def color(
|
|
331
|
+
cls,
|
|
332
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
333
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
334
|
+
name: TYPE_INPUT_STRING = "",
|
|
335
|
+
value: TYPE_INPUT_COLOR = None,
|
|
336
|
+
) -> "StoreNamedAttribute":
|
|
337
|
+
"""Create Store Named Attribute with operation 'Color'."""
|
|
338
|
+
return cls(
|
|
339
|
+
data_type="FLOAT_COLOR",
|
|
340
|
+
geometry=geometry,
|
|
341
|
+
selection=selection,
|
|
342
|
+
name=name,
|
|
343
|
+
value=value,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
@classmethod
|
|
347
|
+
def quaternion(
|
|
348
|
+
cls,
|
|
349
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
350
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
351
|
+
name: TYPE_INPUT_STRING = "",
|
|
352
|
+
value: TYPE_INPUT_ROTATION = None,
|
|
353
|
+
) -> "StoreNamedAttribute":
|
|
354
|
+
"""Create Store Named Attribute with operation 'Quaternion'."""
|
|
355
|
+
return cls(
|
|
356
|
+
data_type="QUATERNION",
|
|
357
|
+
geometry=geometry,
|
|
358
|
+
selection=selection,
|
|
359
|
+
name=name,
|
|
360
|
+
value=value,
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
@classmethod
|
|
364
|
+
def point(
|
|
365
|
+
cls,
|
|
366
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
367
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
368
|
+
name: TYPE_INPUT_STRING = "",
|
|
369
|
+
value: TYPE_INPUT_COLOR = None,
|
|
370
|
+
) -> "StoreNamedAttribute":
|
|
371
|
+
"""Create Store Named Attribute with operation 'Point'."""
|
|
372
|
+
return cls(
|
|
373
|
+
domain="POINT",
|
|
374
|
+
geometry=geometry,
|
|
375
|
+
selection=selection,
|
|
376
|
+
name=name,
|
|
377
|
+
value=value,
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
@classmethod
|
|
381
|
+
def edge(
|
|
382
|
+
cls,
|
|
383
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
384
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
385
|
+
name: TYPE_INPUT_STRING = "",
|
|
386
|
+
value: TYPE_INPUT_COLOR = None,
|
|
387
|
+
) -> "StoreNamedAttribute":
|
|
388
|
+
"""Create Store Named Attribute with operation 'Edge'."""
|
|
389
|
+
return cls(
|
|
390
|
+
domain="EDGE",
|
|
391
|
+
geometry=geometry,
|
|
392
|
+
selection=selection,
|
|
393
|
+
name=name,
|
|
394
|
+
value=value,
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
@classmethod
|
|
398
|
+
def face(
|
|
399
|
+
cls,
|
|
400
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
401
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
402
|
+
name: TYPE_INPUT_STRING = "",
|
|
403
|
+
value: TYPE_INPUT_COLOR = None,
|
|
404
|
+
) -> "StoreNamedAttribute":
|
|
405
|
+
"""Create Store Named Attribute with operation 'Face'."""
|
|
406
|
+
return cls(
|
|
407
|
+
domain="FACE",
|
|
408
|
+
geometry=geometry,
|
|
409
|
+
selection=selection,
|
|
410
|
+
name=name,
|
|
411
|
+
value=value,
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
@classmethod
|
|
415
|
+
def spline(
|
|
416
|
+
cls,
|
|
417
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
418
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
419
|
+
name: TYPE_INPUT_STRING = "",
|
|
420
|
+
value: TYPE_INPUT_COLOR = None,
|
|
421
|
+
) -> "StoreNamedAttribute":
|
|
422
|
+
"""Create Store Named Attribute with operation 'Spline'."""
|
|
423
|
+
return cls(
|
|
424
|
+
domain="CURVE",
|
|
425
|
+
geometry=geometry,
|
|
426
|
+
selection=selection,
|
|
427
|
+
name=name,
|
|
428
|
+
value=value,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
@classmethod
|
|
432
|
+
def instance(
|
|
433
|
+
cls,
|
|
434
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
435
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
436
|
+
name: TYPE_INPUT_STRING = "",
|
|
437
|
+
value: TYPE_INPUT_COLOR = None,
|
|
438
|
+
) -> "StoreNamedAttribute":
|
|
439
|
+
"""Create Store Named Attribute with operation 'Instance'."""
|
|
440
|
+
return cls(
|
|
441
|
+
domain="INSTANCE",
|
|
442
|
+
geometry=geometry,
|
|
443
|
+
selection=selection,
|
|
444
|
+
name=name,
|
|
445
|
+
value=value,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
@classmethod
|
|
449
|
+
def layer(
|
|
450
|
+
cls,
|
|
451
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
452
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
453
|
+
name: TYPE_INPUT_STRING = "",
|
|
454
|
+
value: TYPE_INPUT_COLOR = None,
|
|
455
|
+
) -> "StoreNamedAttribute":
|
|
456
|
+
"""Create Store Named Attribute with operation 'Layer'."""
|
|
457
|
+
return cls(
|
|
458
|
+
domain="LAYER",
|
|
459
|
+
geometry=geometry,
|
|
460
|
+
selection=selection,
|
|
461
|
+
name=name,
|
|
462
|
+
value=value,
|
|
463
|
+
)
|
|
464
|
+
|
|
336
465
|
@property
|
|
337
466
|
def i_geometry(self) -> SocketLinker:
|
|
338
467
|
"""Input socket: Geometry"""
|
|
@@ -361,121 +490,47 @@ class StoreNamedAttribute(NodeBuilder):
|
|
|
361
490
|
@property
|
|
362
491
|
def data_type(
|
|
363
492
|
self,
|
|
364
|
-
) ->
|
|
365
|
-
|
|
493
|
+
) -> Literal[
|
|
494
|
+
"FLOAT",
|
|
495
|
+
"INT",
|
|
496
|
+
"BOOLEAN",
|
|
497
|
+
"FLOAT_VECTOR",
|
|
498
|
+
"FLOAT_COLOR",
|
|
499
|
+
"QUATERNION",
|
|
500
|
+
"FLOAT4X4",
|
|
501
|
+
"INT8",
|
|
502
|
+
"FLOAT2",
|
|
503
|
+
"BYTE_COLOR",
|
|
504
|
+
]:
|
|
505
|
+
return self.node.data_type
|
|
366
506
|
|
|
367
507
|
@data_type.setter
|
|
368
508
|
def data_type(
|
|
369
509
|
self,
|
|
370
|
-
value:
|
|
510
|
+
value: Literal[
|
|
511
|
+
"FLOAT",
|
|
512
|
+
"INT",
|
|
513
|
+
"BOOLEAN",
|
|
514
|
+
"FLOAT_VECTOR",
|
|
515
|
+
"FLOAT_COLOR",
|
|
516
|
+
"QUATERNION",
|
|
517
|
+
"FLOAT4X4",
|
|
518
|
+
"INT8",
|
|
519
|
+
"FLOAT2",
|
|
520
|
+
"BYTE_COLOR",
|
|
521
|
+
],
|
|
371
522
|
):
|
|
372
523
|
self.node.data_type = value
|
|
373
524
|
|
|
374
525
|
@property
|
|
375
526
|
def domain(
|
|
376
527
|
self,
|
|
377
|
-
) ->
|
|
378
|
-
return self.node.domain
|
|
379
|
-
|
|
380
|
-
@domain.setter
|
|
381
|
-
def domain(
|
|
382
|
-
self,
|
|
383
|
-
value: _AttributeDomains,
|
|
384
|
-
):
|
|
385
|
-
self.node.domain = value
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
def _domain_capture_attribute(domain: _AttributeDomains):
|
|
389
|
-
@classmethod
|
|
390
|
-
def method(
|
|
391
|
-
cls,
|
|
392
|
-
*args: LINKABLE,
|
|
393
|
-
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
394
|
-
**kwargs,
|
|
395
|
-
) -> "CaptureAttribute":
|
|
396
|
-
"""Create an IndexSwitch node with a pre-set domain"""
|
|
397
|
-
return cls(*args, geometry=geometry, domain=domain, **kwargs)
|
|
398
|
-
|
|
399
|
-
return method
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
class CaptureAttribute(NodeBuilder):
|
|
403
|
-
"""Store the result of a field on a geometry and output the data as a node socket. Allows remembering or interpolating data as the geometry changes, such as positions before deformation"""
|
|
404
|
-
|
|
405
|
-
name = "GeometryNodeCaptureAttribute"
|
|
406
|
-
node: bpy.types.GeometryNodeCaptureAttribute
|
|
407
|
-
point = _domain_capture_attribute("POINT")
|
|
408
|
-
edge = _domain_capture_attribute("EDGE")
|
|
409
|
-
face = _domain_capture_attribute("FACE")
|
|
410
|
-
corner = _domain_capture_attribute("CORNER")
|
|
411
|
-
curve = _domain_capture_attribute("CURVE")
|
|
412
|
-
instance = _domain_capture_attribute("INSTANCE")
|
|
413
|
-
layer = _domain_capture_attribute("LAYER")
|
|
414
|
-
|
|
415
|
-
def __init__(
|
|
416
|
-
self,
|
|
417
|
-
*args: LINKABLE,
|
|
418
|
-
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
419
|
-
domain: _AttributeDomains = "POINT",
|
|
420
|
-
**kwargs,
|
|
421
|
-
):
|
|
422
|
-
super().__init__()
|
|
423
|
-
key_args = {"Geometry": geometry}
|
|
424
|
-
self.domain = domain
|
|
425
|
-
key_args.update(self._add_inputs(*args, **kwargs)) # type: ignore
|
|
426
|
-
self._establish_links(**key_args)
|
|
427
|
-
|
|
428
|
-
def _add_socket(self, name: str, type: _AttributeDataTypes):
|
|
429
|
-
item = self.node.capture_items.new(socket_type=type, name=name)
|
|
430
|
-
return self.node.inputs[item.name]
|
|
431
|
-
|
|
432
|
-
def capture(self, value: LINKABLE) -> SocketLinker:
|
|
433
|
-
"""Capture the value to store in the attribute
|
|
434
|
-
|
|
435
|
-
Return the SocketLinker for the output socket
|
|
436
|
-
"""
|
|
437
|
-
# the _add_inputs returns a dictionary but we only want the first key
|
|
438
|
-
# because we are adding a single input
|
|
439
|
-
input_dict = self._add_inputs(value)
|
|
440
|
-
return SocketLinker(self.node.outputs[next(iter(input_dict))])
|
|
441
|
-
|
|
442
|
-
@property
|
|
443
|
-
def outputs(self) -> dict[str, SocketLinker]:
|
|
444
|
-
return {
|
|
445
|
-
item.name: SocketLinker(self.node.outputs[item.name])
|
|
446
|
-
for item in self.node.capture_items
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
@property
|
|
450
|
-
def inputs(self) -> dict[str, SocketLinker]:
|
|
451
|
-
return {
|
|
452
|
-
item.name: SocketLinker(self.node.inputs[item.name])
|
|
453
|
-
for item in self.node.capture_items
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
@property
|
|
457
|
-
def _items(self) -> bpy.types.NodeGeometryCaptureAttributeItems:
|
|
458
|
-
return self.node.capture_items
|
|
459
|
-
|
|
460
|
-
@property
|
|
461
|
-
def i_geometry(self) -> SocketLinker:
|
|
462
|
-
"""Input socket: Geometry"""
|
|
463
|
-
return self._input("Geometry")
|
|
464
|
-
|
|
465
|
-
@property
|
|
466
|
-
def o_geometry(self) -> SocketLinker:
|
|
467
|
-
"""Output socket: Geometry"""
|
|
468
|
-
return self._output("Geometry")
|
|
469
|
-
|
|
470
|
-
@property
|
|
471
|
-
def domain(
|
|
472
|
-
self,
|
|
473
|
-
) -> _AttributeDomains:
|
|
528
|
+
) -> Literal["POINT", "EDGE", "FACE", "CORNER", "CURVE", "INSTANCE", "LAYER"]:
|
|
474
529
|
return self.node.domain
|
|
475
530
|
|
|
476
531
|
@domain.setter
|
|
477
532
|
def domain(
|
|
478
533
|
self,
|
|
479
|
-
value:
|
|
534
|
+
value: Literal["POINT", "EDGE", "FACE", "CORNER", "CURVE", "INSTANCE", "LAYER"],
|
|
480
535
|
):
|
|
481
536
|
self.node.domain = value
|