nodebpy 0.1.1__py3-none-any.whl → 0.2.0__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 +770 -306
- nodebpy/nodes/__init__.py +623 -9
- nodebpy/nodes/attribute.py +174 -273
- nodebpy/nodes/color.py +76 -0
- nodebpy/nodes/converter.py +4518 -0
- nodebpy/nodes/experimental.py +314 -0
- nodebpy/nodes/geometry.py +3665 -5250
- nodebpy/nodes/grid.py +1228 -0
- nodebpy/nodes/group.py +20 -0
- nodebpy/nodes/input.py +1571 -254
- nodebpy/nodes/interface.py +400 -0
- nodebpy/nodes/mesh.py +0 -1391
- nodebpy/nodes/texture.py +70 -0
- nodebpy/nodes/types.py +319 -6
- nodebpy/nodes/vector.py +0 -0
- nodebpy/nodes/zone.py +442 -0
- nodebpy/screenshot.py +2 -1
- nodebpy/sockets.py +12 -12
- {nodebpy-0.1.1.dist-info → nodebpy-0.2.0.dist-info}/METADATA +4 -4
- nodebpy-0.2.0.dist-info/RECORD +25 -0
- nodebpy/nodes/curve.py +0 -2006
- nodebpy/nodes/manually_specified.py +0 -1382
- nodebpy/nodes/utilities.py +0 -2344
- nodebpy-0.1.1.dist-info/RECORD +0 -19
- {nodebpy-0.1.1.dist-info → nodebpy-0.2.0.dist-info}/WHEEL +0 -0
- {nodebpy-0.1.1.dist-info → nodebpy-0.2.0.dist-info}/entry_points.txt +0 -0
nodebpy/nodes/grid.py
ADDED
|
@@ -0,0 +1,1228 @@
|
|
|
1
|
+
import bpy
|
|
2
|
+
from typing_extensions import Literal
|
|
3
|
+
|
|
4
|
+
from nodebpy.builder import NodeBuilder, SocketLinker
|
|
5
|
+
|
|
6
|
+
from .types import (
|
|
7
|
+
LINKABLE,
|
|
8
|
+
TYPE_INPUT_BOOLEAN,
|
|
9
|
+
TYPE_INPUT_GEOMETRY,
|
|
10
|
+
TYPE_INPUT_GRID,
|
|
11
|
+
TYPE_INPUT_INT,
|
|
12
|
+
TYPE_INPUT_STRING,
|
|
13
|
+
TYPE_INPUT_VALUE,
|
|
14
|
+
TYPE_INPUT_VECTOR,
|
|
15
|
+
_AdvectGridIntegration,
|
|
16
|
+
_GridDataTypes,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DistributePointsInGrid(NodeBuilder):
|
|
21
|
+
"""Generate points inside a volume grid"""
|
|
22
|
+
|
|
23
|
+
name = "GeometryNodeDistributePointsInGrid"
|
|
24
|
+
node: bpy.types.GeometryNodeDistributePointsInGrid
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
grid: LINKABLE = None,
|
|
29
|
+
mode: Literal["DENSITY_RANDOM", "DENSITY_GRID"] = "DENSITY_RANDOM",
|
|
30
|
+
**kwargs,
|
|
31
|
+
):
|
|
32
|
+
super().__init__()
|
|
33
|
+
key_args = {
|
|
34
|
+
"Grid": grid,
|
|
35
|
+
}
|
|
36
|
+
self.mode = mode
|
|
37
|
+
key_args.update(kwargs)
|
|
38
|
+
self._establish_links(**key_args)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def grid(
|
|
42
|
+
cls,
|
|
43
|
+
grid: LINKABLE,
|
|
44
|
+
spacing: TYPE_INPUT_VECTOR = (0.3, 0.3, 0.3),
|
|
45
|
+
threshold: TYPE_INPUT_VALUE = 0.1,
|
|
46
|
+
) -> "DistributePointsInGrid":
|
|
47
|
+
return cls(grid=grid, Spacing=spacing, Threshold=threshold, mode="DENSITY_GRID")
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def random(
|
|
51
|
+
cls,
|
|
52
|
+
grid: LINKABLE,
|
|
53
|
+
density: TYPE_INPUT_VALUE = 1.0,
|
|
54
|
+
seed: TYPE_INPUT_INT = 0,
|
|
55
|
+
) -> "DistributePointsInGrid":
|
|
56
|
+
return cls(grid=grid, Density=density, Seed=seed, mode="DENSITY_RANDOM")
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def i_grid(self) -> SocketLinker:
|
|
60
|
+
"""Input socket: Grid"""
|
|
61
|
+
return self._input("Grid")
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def i_density(self) -> SocketLinker:
|
|
65
|
+
"""Input socket: Density"""
|
|
66
|
+
return self._input("Density")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def i_seed(self) -> SocketLinker:
|
|
70
|
+
"""Input socket: Seed"""
|
|
71
|
+
return self._input("Seed")
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def o_points(self) -> SocketLinker:
|
|
75
|
+
"""Output socket: Points"""
|
|
76
|
+
return self._output("Points")
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def mode(self) -> Literal["DENSITY_RANDOM", "DENSITY_GRID"]:
|
|
80
|
+
return self.node.mode
|
|
81
|
+
|
|
82
|
+
@mode.setter
|
|
83
|
+
def mode(self, value: Literal["DENSITY_RANDOM", "DENSITY_GRID"]):
|
|
84
|
+
self.node.mode = value
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class DistributePointsInVolume(NodeBuilder):
|
|
88
|
+
"""Generate points inside a volume"""
|
|
89
|
+
|
|
90
|
+
name = "GeometryNodeDistributePointsInVolume"
|
|
91
|
+
node: bpy.types.GeometryNodeDistributePointsInVolume
|
|
92
|
+
|
|
93
|
+
def __init__(
|
|
94
|
+
self,
|
|
95
|
+
volume: TYPE_INPUT_GEOMETRY = None,
|
|
96
|
+
mode: Literal["Random", "Grid"] = "Random",
|
|
97
|
+
**kwargs,
|
|
98
|
+
):
|
|
99
|
+
super().__init__()
|
|
100
|
+
key_args = {
|
|
101
|
+
"Volume": volume,
|
|
102
|
+
"Mode": mode,
|
|
103
|
+
}
|
|
104
|
+
key_args.update(kwargs)
|
|
105
|
+
self._establish_links(**key_args)
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def grid(
|
|
109
|
+
cls,
|
|
110
|
+
volume: TYPE_INPUT_GEOMETRY = None,
|
|
111
|
+
density: TYPE_INPUT_VALUE = 1.0,
|
|
112
|
+
seed: TYPE_INPUT_INT = 0,
|
|
113
|
+
):
|
|
114
|
+
return cls(volume=volume, Density=density, Seed=seed, mode="Grid")
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def random(
|
|
118
|
+
cls,
|
|
119
|
+
volume: TYPE_INPUT_GEOMETRY = None,
|
|
120
|
+
spacing: TYPE_INPUT_VECTOR = (0.3, 0.3, 0.3),
|
|
121
|
+
threshold: TYPE_INPUT_VALUE = 0.1,
|
|
122
|
+
):
|
|
123
|
+
return cls(volume=volume, Space=spacing, Threshold=threshold, mode="Random")
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def i_density(self) -> SocketLinker:
|
|
127
|
+
"""Input socket: Density"""
|
|
128
|
+
return self._input("Density")
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def i_seed(self) -> SocketLinker:
|
|
132
|
+
"""Input socket: Seed"""
|
|
133
|
+
return self._input("Seed")
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def i_spacing(self) -> SocketLinker:
|
|
137
|
+
"""Input socket: Spacing"""
|
|
138
|
+
return self._input("Spacing")
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def i_threshold(self) -> SocketLinker:
|
|
142
|
+
"""Input socket: Threshold"""
|
|
143
|
+
return self._input("Threshold")
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def o_points(self) -> SocketLinker:
|
|
147
|
+
"""Output socket: Points"""
|
|
148
|
+
return self._output("Points")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class FieldToGrid(NodeBuilder):
|
|
152
|
+
"""Create new grids by evaluating new values on an existing volume grid topology
|
|
153
|
+
|
|
154
|
+
New socket items for field evaluation are first created from *args then **kwargs to give specific names to the items.
|
|
155
|
+
|
|
156
|
+
Data types are inferred automatically from the closest compatible data type.
|
|
157
|
+
|
|
158
|
+
Inputs:
|
|
159
|
+
-------
|
|
160
|
+
topology: LINKABLE
|
|
161
|
+
The grid which contains the topology to evaluate the different fields on.
|
|
162
|
+
data_type: _GridDataTypes = "FLOAT"
|
|
163
|
+
The data type of the grid to evaluate on. Possible values are "FLOAT", "INT", "VECTOR", "BOOLEAN".
|
|
164
|
+
*args: TYPE_INPUT_VALUE | TYPE_INPUT_VECTOR | TYPE_INPUT_INT | TYPE_INPUT_BOOLEAN
|
|
165
|
+
The fields to evaluate on the grid.
|
|
166
|
+
**kwargs: dict[str, TYPE_INPUT_VALUE | TYPE_INPUT_VECTOR | TYPE_INPUT_INT | TYPE_INPUT_GEOMETRY]
|
|
167
|
+
The key-value pairs of the fields to evaluate on the grid. Keys will be used as the name of the socket.
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
name = "GeometryNodeFieldToGrid"
|
|
172
|
+
node: bpy.types.GeometryNodeFieldToGrid
|
|
173
|
+
_socket_data_types = ("FLOAT", "VALUE", "INT", "VECTOR", "BOOLEAN")
|
|
174
|
+
_default_input_id = "Topology"
|
|
175
|
+
|
|
176
|
+
def __init__(
|
|
177
|
+
self,
|
|
178
|
+
*args: TYPE_INPUT_GRID,
|
|
179
|
+
topology: TYPE_INPUT_GRID = None,
|
|
180
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
181
|
+
**kwargs: TYPE_INPUT_GRID,
|
|
182
|
+
):
|
|
183
|
+
super().__init__()
|
|
184
|
+
self.data_type = data_type
|
|
185
|
+
key_args = {
|
|
186
|
+
"Topology": topology,
|
|
187
|
+
}
|
|
188
|
+
key_args.update(self._add_inputs(*args, **kwargs)) # type: ignore
|
|
189
|
+
self._establish_links(**key_args)
|
|
190
|
+
|
|
191
|
+
def _add_socket( # type: ignore
|
|
192
|
+
self,
|
|
193
|
+
name: str,
|
|
194
|
+
type: _GridDataTypes = "FLOAT",
|
|
195
|
+
default_value: float | int | str | None = None,
|
|
196
|
+
):
|
|
197
|
+
item = self.node.grid_items.new(socket_type=type, name=name)
|
|
198
|
+
if default_value is not None:
|
|
199
|
+
try:
|
|
200
|
+
self.node.inputs[item.name].default_value = default_value # type: ignore
|
|
201
|
+
except TypeError as e:
|
|
202
|
+
raise ValueError(
|
|
203
|
+
f"Invalid default value for {type}: {default_value}"
|
|
204
|
+
) from e
|
|
205
|
+
return self.node.inputs[item.name]
|
|
206
|
+
|
|
207
|
+
def capture(self, *args, **kwargs) -> list[SocketLinker]:
|
|
208
|
+
outputs = {
|
|
209
|
+
name: self.node.outputs[name] for name in self._add_inputs(*args, **kwargs)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return [SocketLinker(x) for x in outputs.values()]
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def outputs(self) -> dict[str, SocketLinker]:
|
|
216
|
+
return {
|
|
217
|
+
item.name: SocketLinker(self.node.outputs[item.name])
|
|
218
|
+
for item in self.node.grid_items
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def inputs(self) -> dict[str, SocketLinker]:
|
|
223
|
+
return {
|
|
224
|
+
item.name: SocketLinker(self.node.inputs[item.name])
|
|
225
|
+
for item in self.node.grid_items
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def i_topology(self) -> SocketLinker:
|
|
230
|
+
"""Input socket: Topology"""
|
|
231
|
+
return self._input("Topology")
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def data_type(
|
|
235
|
+
self,
|
|
236
|
+
) -> _GridDataTypes:
|
|
237
|
+
return self.node.data_type # type: ignore
|
|
238
|
+
|
|
239
|
+
@data_type.setter
|
|
240
|
+
def data_type(
|
|
241
|
+
self,
|
|
242
|
+
value: _GridDataTypes,
|
|
243
|
+
):
|
|
244
|
+
self.node.data_type = value
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class GetNamedGrid(NodeBuilder):
|
|
248
|
+
"""Get volume grid from a volume geometry with the specified name"""
|
|
249
|
+
|
|
250
|
+
name = "GeometryNodeGetNamedGrid"
|
|
251
|
+
node: bpy.types.GeometryNodeGetNamedGrid
|
|
252
|
+
_default_input_id = "Volume"
|
|
253
|
+
|
|
254
|
+
def __init__(
|
|
255
|
+
self,
|
|
256
|
+
volume: TYPE_INPUT_GEOMETRY = None,
|
|
257
|
+
name: TYPE_INPUT_STRING = "",
|
|
258
|
+
remove: TYPE_INPUT_BOOLEAN = True,
|
|
259
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
260
|
+
):
|
|
261
|
+
super().__init__()
|
|
262
|
+
key_args = {"Volume": volume, "Name": name, "Remove": remove}
|
|
263
|
+
self.data_type = data_type
|
|
264
|
+
self._establish_links(**key_args)
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def i_volume(self) -> SocketLinker:
|
|
268
|
+
"""Input socket: Volume"""
|
|
269
|
+
return self._input("Volume")
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def i_name(self) -> SocketLinker:
|
|
273
|
+
"""Input socket: Name"""
|
|
274
|
+
return self._input("Name")
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def i_remove(self) -> SocketLinker:
|
|
278
|
+
"""Input socket: Remove"""
|
|
279
|
+
return self._input("Remove")
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def o_volume(self) -> SocketLinker:
|
|
283
|
+
"""Output socket: Volume"""
|
|
284
|
+
return self._output("Volume")
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def o_grid(self) -> SocketLinker:
|
|
288
|
+
"""Output socket: Grid"""
|
|
289
|
+
return self._output("Grid")
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def data_type(
|
|
293
|
+
self,
|
|
294
|
+
) -> _GridDataTypes:
|
|
295
|
+
return self.node.data_type # type: ignore
|
|
296
|
+
|
|
297
|
+
@data_type.setter
|
|
298
|
+
def data_type(
|
|
299
|
+
self,
|
|
300
|
+
value: _GridDataTypes,
|
|
301
|
+
):
|
|
302
|
+
self.node.data_type = value
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class AdvectGrid(NodeBuilder):
|
|
306
|
+
"""Move grid values through a velocity field using numerical integration. Supports multiple integration schemes for different accuracy and performance trade-offs"""
|
|
307
|
+
|
|
308
|
+
name = "GeometryNodeGridAdvect"
|
|
309
|
+
node: bpy.types.GeometryNodeGridAdvect
|
|
310
|
+
_socket_data_types = ["FLOAT", "VALUE", "INT", "VECTOR"]
|
|
311
|
+
|
|
312
|
+
def __init__(
|
|
313
|
+
self,
|
|
314
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
315
|
+
velocity: TYPE_INPUT_VECTOR = None,
|
|
316
|
+
time_step: TYPE_INPUT_VALUE = 1.0,
|
|
317
|
+
*,
|
|
318
|
+
integration_scheme: _AdvectGridIntegration = "Runge-Kutta 3",
|
|
319
|
+
limiter: Literal["None", "Clamp", "Revert"] = "Clamp",
|
|
320
|
+
data_type: Literal["FLOAT", "INT", "VECTOR"] = "FLOAT",
|
|
321
|
+
):
|
|
322
|
+
super().__init__()
|
|
323
|
+
key_args = {
|
|
324
|
+
"Grid": grid,
|
|
325
|
+
"Velocity": velocity,
|
|
326
|
+
"Time Step": time_step,
|
|
327
|
+
"Integration Scheme": integration_scheme,
|
|
328
|
+
"Limiter": limiter,
|
|
329
|
+
}
|
|
330
|
+
self.data_type = data_type
|
|
331
|
+
self._establish_links(**key_args)
|
|
332
|
+
|
|
333
|
+
@property
|
|
334
|
+
def i_grid(self) -> SocketLinker:
|
|
335
|
+
"""Input socket: Grid"""
|
|
336
|
+
return self._input("Grid")
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def i_velocity(self) -> SocketLinker:
|
|
340
|
+
"""Input socket: Velocity"""
|
|
341
|
+
return self._input("Velocity")
|
|
342
|
+
|
|
343
|
+
@property
|
|
344
|
+
def i_time_step(self) -> SocketLinker:
|
|
345
|
+
"""Input socket: Time Step"""
|
|
346
|
+
return self._input("Time Step")
|
|
347
|
+
|
|
348
|
+
@property
|
|
349
|
+
def i_integration_scheme(self) -> SocketLinker:
|
|
350
|
+
"""Input socket: Integration Scheme"""
|
|
351
|
+
return self._input("Integration Scheme")
|
|
352
|
+
|
|
353
|
+
@property
|
|
354
|
+
def i_limiter(self) -> SocketLinker:
|
|
355
|
+
"""Input socket: Limiter"""
|
|
356
|
+
return self._input("Limiter")
|
|
357
|
+
|
|
358
|
+
@property
|
|
359
|
+
def o_grid(self) -> SocketLinker:
|
|
360
|
+
"""Output socket: Grid"""
|
|
361
|
+
return self._output("Grid")
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def data_type(
|
|
365
|
+
self,
|
|
366
|
+
) -> Literal["FLOAT", "INT", "VECTOR"]:
|
|
367
|
+
return self.node.data_type # type: ignore
|
|
368
|
+
|
|
369
|
+
@data_type.setter
|
|
370
|
+
def data_type(
|
|
371
|
+
self,
|
|
372
|
+
value: Literal["FLOAT", "INT", "VECTOR"],
|
|
373
|
+
):
|
|
374
|
+
self.node.data_type = value
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
class GridCurl(NodeBuilder):
|
|
378
|
+
"""Calculate the magnitude and direction of circulation of a directional vector grid"""
|
|
379
|
+
|
|
380
|
+
name = "GeometryNodeGridCurl"
|
|
381
|
+
node: bpy.types.GeometryNodeGridCurl
|
|
382
|
+
|
|
383
|
+
def __init__(self, grid: TYPE_INPUT_VECTOR = None):
|
|
384
|
+
super().__init__()
|
|
385
|
+
key_args = {"Grid": grid}
|
|
386
|
+
self._establish_links(**key_args)
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def i_grid(self) -> SocketLinker:
|
|
390
|
+
"""Input socket: Grid"""
|
|
391
|
+
return self._input("Grid")
|
|
392
|
+
|
|
393
|
+
@property
|
|
394
|
+
def o_curl(self) -> SocketLinker:
|
|
395
|
+
"""Output socket: Curl"""
|
|
396
|
+
return self._output("Curl")
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class GridDivergence(NodeBuilder):
|
|
400
|
+
"""Calculate the flow into and out of each point of a directional vector grid"""
|
|
401
|
+
|
|
402
|
+
name = "GeometryNodeGridDivergence"
|
|
403
|
+
node: bpy.types.GeometryNodeGridDivergence
|
|
404
|
+
|
|
405
|
+
def __init__(self, grid: TYPE_INPUT_VECTOR = None):
|
|
406
|
+
super().__init__()
|
|
407
|
+
key_args = {"Grid": grid}
|
|
408
|
+
self._establish_links(**key_args)
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def i_grid(self) -> SocketLinker:
|
|
412
|
+
"""Input socket: Grid"""
|
|
413
|
+
return self._input("Grid")
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def o_divergence(self) -> SocketLinker:
|
|
417
|
+
"""Output socket: Divergence"""
|
|
418
|
+
return self._output("Divergence")
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class GridGradient(NodeBuilder):
|
|
422
|
+
"""Calculate the direction and magnitude of the change in values of a scalar grid"""
|
|
423
|
+
|
|
424
|
+
name = "GeometryNodeGridGradient"
|
|
425
|
+
node: bpy.types.GeometryNodeGridGradient
|
|
426
|
+
|
|
427
|
+
def __init__(self, grid: TYPE_INPUT_VALUE = None):
|
|
428
|
+
super().__init__()
|
|
429
|
+
key_args = {"Grid": grid}
|
|
430
|
+
self._establish_links(**key_args)
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def i_grid(self) -> SocketLinker:
|
|
434
|
+
"""Input socket: Grid"""
|
|
435
|
+
return self._input("Grid")
|
|
436
|
+
|
|
437
|
+
@property
|
|
438
|
+
def o_gradient(self) -> SocketLinker:
|
|
439
|
+
"""Output socket: Gradient"""
|
|
440
|
+
return self._output("Gradient")
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class GridInfo(NodeBuilder):
|
|
444
|
+
"""Retrieve information about a volume grid"""
|
|
445
|
+
|
|
446
|
+
name = "GeometryNodeGridInfo"
|
|
447
|
+
node: bpy.types.GeometryNodeGridInfo
|
|
448
|
+
|
|
449
|
+
def __init__(
|
|
450
|
+
self, grid: TYPE_INPUT_GRID = None, data_type: _GridDataTypes = "FLOAT"
|
|
451
|
+
):
|
|
452
|
+
super().__init__()
|
|
453
|
+
key_args = {"Grid": grid}
|
|
454
|
+
self.data_type = data_type
|
|
455
|
+
self._establish_links(**key_args)
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def i_grid(self) -> SocketLinker:
|
|
459
|
+
"""Input socket: Grid"""
|
|
460
|
+
return self._input("Grid")
|
|
461
|
+
|
|
462
|
+
@property
|
|
463
|
+
def o_transform(self) -> SocketLinker:
|
|
464
|
+
"""Output socket: Transform"""
|
|
465
|
+
return self._output("Transform")
|
|
466
|
+
|
|
467
|
+
@property
|
|
468
|
+
def o_background_value(self) -> SocketLinker:
|
|
469
|
+
"""Output socket: Background Value"""
|
|
470
|
+
return self._output("Background Value")
|
|
471
|
+
|
|
472
|
+
@property
|
|
473
|
+
def data_type(
|
|
474
|
+
self,
|
|
475
|
+
) -> _GridDataTypes:
|
|
476
|
+
return self.node.data_type # type: ignore
|
|
477
|
+
|
|
478
|
+
@data_type.setter
|
|
479
|
+
def data_type(
|
|
480
|
+
self,
|
|
481
|
+
value: _GridDataTypes,
|
|
482
|
+
):
|
|
483
|
+
self.node.data_type = value
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class GridLaplacian(NodeBuilder):
|
|
487
|
+
"""Compute the divergence of the gradient of the input grid"""
|
|
488
|
+
|
|
489
|
+
name = "GeometryNodeGridLaplacian"
|
|
490
|
+
node: bpy.types.GeometryNodeGridLaplacian
|
|
491
|
+
|
|
492
|
+
def __init__(self, grid: TYPE_INPUT_VALUE = None):
|
|
493
|
+
super().__init__()
|
|
494
|
+
key_args = {"Grid": grid}
|
|
495
|
+
self._establish_links(**key_args)
|
|
496
|
+
|
|
497
|
+
@property
|
|
498
|
+
def i_grid(self) -> SocketLinker:
|
|
499
|
+
"""Input socket: Grid"""
|
|
500
|
+
return self._input("Grid")
|
|
501
|
+
|
|
502
|
+
@property
|
|
503
|
+
def o_laplacian(self) -> SocketLinker:
|
|
504
|
+
"""Output socket: Laplacian"""
|
|
505
|
+
return self._output("Laplacian")
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
class PruneGrid(NodeBuilder):
|
|
509
|
+
"""Make the storage of a volume grid more efficient by collapsing data into tiles or inner nodes"""
|
|
510
|
+
|
|
511
|
+
name = "GeometryNodeGridPrune"
|
|
512
|
+
node: bpy.types.GeometryNodeGridPrune
|
|
513
|
+
|
|
514
|
+
def __init__(
|
|
515
|
+
self,
|
|
516
|
+
grid: TYPE_INPUT_GRID = None,
|
|
517
|
+
*,
|
|
518
|
+
mode: Literal["Inactive", "Threshold", "SDF"] = "Threshold",
|
|
519
|
+
threshold: TYPE_INPUT_VALUE = 0.01,
|
|
520
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
521
|
+
):
|
|
522
|
+
super().__init__()
|
|
523
|
+
key_args = {"Grid": grid, "Mode": mode, "Threshold": threshold}
|
|
524
|
+
self.data_type = data_type
|
|
525
|
+
self._establish_links(**key_args)
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def i_grid(self) -> SocketLinker:
|
|
529
|
+
"""Input socket: Grid"""
|
|
530
|
+
return self._input("Grid")
|
|
531
|
+
|
|
532
|
+
@property
|
|
533
|
+
def i_mode(self) -> SocketLinker:
|
|
534
|
+
"""Input socket: Mode"""
|
|
535
|
+
return self._input("Mode")
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def i_threshold(self) -> SocketLinker:
|
|
539
|
+
"""Input socket: Threshold"""
|
|
540
|
+
return self._input("Threshold")
|
|
541
|
+
|
|
542
|
+
@property
|
|
543
|
+
def o_grid(self) -> SocketLinker:
|
|
544
|
+
"""Output socket: Grid"""
|
|
545
|
+
return self._output("Grid")
|
|
546
|
+
|
|
547
|
+
@property
|
|
548
|
+
def data_type(
|
|
549
|
+
self,
|
|
550
|
+
) -> _GridDataTypes:
|
|
551
|
+
return self.node.data_type # type: ignore
|
|
552
|
+
|
|
553
|
+
@data_type.setter
|
|
554
|
+
def data_type(
|
|
555
|
+
self,
|
|
556
|
+
value: _GridDataTypes,
|
|
557
|
+
):
|
|
558
|
+
self.node.data_type = value
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
class VoxelizeGrid(NodeBuilder):
|
|
562
|
+
"""Remove sparseness from a volume grid by making the active tiles into voxels"""
|
|
563
|
+
|
|
564
|
+
name = "GeometryNodeGridVoxelize"
|
|
565
|
+
node: bpy.types.GeometryNodeGridVoxelize
|
|
566
|
+
|
|
567
|
+
def __init__(
|
|
568
|
+
self, grid: TYPE_INPUT_GRID = None, data_type: _GridDataTypes = "FLOAT"
|
|
569
|
+
):
|
|
570
|
+
super().__init__()
|
|
571
|
+
key_args = {"Grid": grid}
|
|
572
|
+
self.data_type = data_type
|
|
573
|
+
self._establish_links(**key_args)
|
|
574
|
+
|
|
575
|
+
@property
|
|
576
|
+
def i_grid(self) -> SocketLinker:
|
|
577
|
+
"""Input socket: Grid"""
|
|
578
|
+
return self._input("Grid")
|
|
579
|
+
|
|
580
|
+
@property
|
|
581
|
+
def o_grid(self) -> SocketLinker:
|
|
582
|
+
"""Output socket: Grid"""
|
|
583
|
+
return self._output("Grid")
|
|
584
|
+
|
|
585
|
+
@property
|
|
586
|
+
def data_type(
|
|
587
|
+
self,
|
|
588
|
+
) -> _GridDataTypes:
|
|
589
|
+
return self.node.data_type # type: ignore
|
|
590
|
+
|
|
591
|
+
@data_type.setter
|
|
592
|
+
def data_type(
|
|
593
|
+
self,
|
|
594
|
+
value: _GridDataTypes,
|
|
595
|
+
):
|
|
596
|
+
self.node.data_type = value
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
class VolumeCube(NodeBuilder):
|
|
600
|
+
"""Generate a dense volume with a field that controls the density at each grid voxel based on its position"""
|
|
601
|
+
|
|
602
|
+
name = "GeometryNodeVolumeCube"
|
|
603
|
+
node: bpy.types.GeometryNodeVolumeCube
|
|
604
|
+
|
|
605
|
+
def __init__(
|
|
606
|
+
self,
|
|
607
|
+
density: TYPE_INPUT_VALUE = 1.0,
|
|
608
|
+
background: TYPE_INPUT_VALUE = 0.0,
|
|
609
|
+
min: TYPE_INPUT_VECTOR = (-1.0, -1.0, -1.0),
|
|
610
|
+
max: TYPE_INPUT_VECTOR = (1.0, 1.0, 1.0),
|
|
611
|
+
resolution_x: TYPE_INPUT_INT = 32,
|
|
612
|
+
resolution_y: TYPE_INPUT_INT = 32,
|
|
613
|
+
resolution_z: TYPE_INPUT_INT = 32,
|
|
614
|
+
):
|
|
615
|
+
super().__init__()
|
|
616
|
+
key_args = {
|
|
617
|
+
"Density": density,
|
|
618
|
+
"Background": background,
|
|
619
|
+
"Min": min,
|
|
620
|
+
"Max": max,
|
|
621
|
+
"Resolution X": resolution_x,
|
|
622
|
+
"Resolution Y": resolution_y,
|
|
623
|
+
"Resolution Z": resolution_z,
|
|
624
|
+
}
|
|
625
|
+
self._establish_links(**key_args)
|
|
626
|
+
|
|
627
|
+
@property
|
|
628
|
+
def i_density(self) -> SocketLinker:
|
|
629
|
+
"""Input socket: Density"""
|
|
630
|
+
return self._input("Density")
|
|
631
|
+
|
|
632
|
+
@property
|
|
633
|
+
def i_background(self) -> SocketLinker:
|
|
634
|
+
"""Input socket: Background"""
|
|
635
|
+
return self._input("Background")
|
|
636
|
+
|
|
637
|
+
@property
|
|
638
|
+
def i_min(self) -> SocketLinker:
|
|
639
|
+
"""Input socket: Min"""
|
|
640
|
+
return self._input("Min")
|
|
641
|
+
|
|
642
|
+
@property
|
|
643
|
+
def i_max(self) -> SocketLinker:
|
|
644
|
+
"""Input socket: Max"""
|
|
645
|
+
return self._input("Max")
|
|
646
|
+
|
|
647
|
+
@property
|
|
648
|
+
def i_resolution_x(self) -> SocketLinker:
|
|
649
|
+
"""Input socket: Resolution X"""
|
|
650
|
+
return self._input("Resolution X")
|
|
651
|
+
|
|
652
|
+
@property
|
|
653
|
+
def i_resolution_y(self) -> SocketLinker:
|
|
654
|
+
"""Input socket: Resolution Y"""
|
|
655
|
+
return self._input("Resolution Y")
|
|
656
|
+
|
|
657
|
+
@property
|
|
658
|
+
def i_resolution_z(self) -> SocketLinker:
|
|
659
|
+
"""Input socket: Resolution Z"""
|
|
660
|
+
return self._input("Resolution Z")
|
|
661
|
+
|
|
662
|
+
@property
|
|
663
|
+
def o_volume(self) -> SocketLinker:
|
|
664
|
+
"""Output socket: Volume"""
|
|
665
|
+
return self._output("Volume")
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
class SDFGridBoolean(NodeBuilder):
|
|
669
|
+
"""Cut, subtract, or join multiple SDF volume grid inputs"""
|
|
670
|
+
|
|
671
|
+
name = "GeometryNodeSDFGridBoolean"
|
|
672
|
+
node: bpy.types.GeometryNodeSDFGridBoolean
|
|
673
|
+
|
|
674
|
+
def __init__(
|
|
675
|
+
self, *, operation: Literal["INTERSECT", "UNION", "DIFFERENCE"] = "DIFFERENCE"
|
|
676
|
+
):
|
|
677
|
+
super().__init__()
|
|
678
|
+
self.operation = operation
|
|
679
|
+
|
|
680
|
+
@classmethod
|
|
681
|
+
def intersect(
|
|
682
|
+
cls,
|
|
683
|
+
*args: LINKABLE,
|
|
684
|
+
) -> "SDFGridBoolean":
|
|
685
|
+
node = cls(operation="INTERSECT")
|
|
686
|
+
for arg in args:
|
|
687
|
+
if arg is None:
|
|
688
|
+
continue
|
|
689
|
+
node._link_from(arg, "Grid 2")
|
|
690
|
+
return node
|
|
691
|
+
|
|
692
|
+
@classmethod
|
|
693
|
+
def union(
|
|
694
|
+
cls,
|
|
695
|
+
*args: LINKABLE,
|
|
696
|
+
) -> "SDFGridBoolean":
|
|
697
|
+
node = cls(operation="UNION")
|
|
698
|
+
for arg in args:
|
|
699
|
+
if arg is None:
|
|
700
|
+
continue
|
|
701
|
+
node._link_from(arg, "Grid 2")
|
|
702
|
+
return node
|
|
703
|
+
|
|
704
|
+
@classmethod
|
|
705
|
+
def difference(
|
|
706
|
+
cls,
|
|
707
|
+
*args: LINKABLE,
|
|
708
|
+
grid_1: LINKABLE,
|
|
709
|
+
) -> "SDFGridBoolean":
|
|
710
|
+
"""Create SDF Grid Boolean with operation 'Difference'."""
|
|
711
|
+
node = cls(operation="DIFFERENCE")
|
|
712
|
+
node._link_from(grid_1, "Grid 1")
|
|
713
|
+
for arg in args:
|
|
714
|
+
if arg is None:
|
|
715
|
+
continue
|
|
716
|
+
node._link_from(arg, "Grid 2")
|
|
717
|
+
return node
|
|
718
|
+
|
|
719
|
+
@property
|
|
720
|
+
def i_grid_1(self) -> SocketLinker:
|
|
721
|
+
"""Input socket: Grid 1"""
|
|
722
|
+
return self._input("Grid 1")
|
|
723
|
+
|
|
724
|
+
@property
|
|
725
|
+
def i_grid_2(self) -> SocketLinker:
|
|
726
|
+
"""Input socket: Grid 2"""
|
|
727
|
+
return self._input("Grid 2")
|
|
728
|
+
|
|
729
|
+
@property
|
|
730
|
+
def o_grid(self) -> SocketLinker:
|
|
731
|
+
"""Output socket: Grid"""
|
|
732
|
+
return self._output("Grid")
|
|
733
|
+
|
|
734
|
+
@property
|
|
735
|
+
def operation(self) -> Literal["INTERSECT", "UNION", "DIFFERENCE"]:
|
|
736
|
+
return self.node.operation
|
|
737
|
+
|
|
738
|
+
@operation.setter
|
|
739
|
+
def operation(self, value: Literal["INTERSECT", "UNION", "DIFFERENCE"]):
|
|
740
|
+
self.node.operation = value
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
class SDFGridFillet(NodeBuilder):
|
|
744
|
+
"""Round off concave internal corners in a signed distance field. Only affects areas with negative principal curvature, creating smoother transitions between surfaces"""
|
|
745
|
+
|
|
746
|
+
name = "GeometryNodeSDFGridFillet"
|
|
747
|
+
node: bpy.types.GeometryNodeSDFGridFillet
|
|
748
|
+
|
|
749
|
+
def __init__(self, grid: TYPE_INPUT_VALUE = None, iterations: TYPE_INPUT_INT = 1):
|
|
750
|
+
super().__init__()
|
|
751
|
+
key_args = {"Grid": grid, "Iterations": iterations}
|
|
752
|
+
self._establish_links(**key_args)
|
|
753
|
+
|
|
754
|
+
@property
|
|
755
|
+
def i_grid(self) -> SocketLinker:
|
|
756
|
+
"""Input socket: Grid"""
|
|
757
|
+
return self._input("Grid")
|
|
758
|
+
|
|
759
|
+
@property
|
|
760
|
+
def i_iterations(self) -> SocketLinker:
|
|
761
|
+
"""Input socket: Iterations"""
|
|
762
|
+
return self._input("Iterations")
|
|
763
|
+
|
|
764
|
+
@property
|
|
765
|
+
def o_grid(self) -> SocketLinker:
|
|
766
|
+
"""Output socket: Grid"""
|
|
767
|
+
return self._output("Grid")
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
class SDFGridLaplacian(NodeBuilder):
|
|
771
|
+
"""Apply Laplacian flow smoothing to a signed distance field. Computationally efficient alternative to mean curvature flow, ideal when combined with SDF normalization"""
|
|
772
|
+
|
|
773
|
+
name = "GeometryNodeSDFGridLaplacian"
|
|
774
|
+
node: bpy.types.GeometryNodeSDFGridLaplacian
|
|
775
|
+
|
|
776
|
+
def __init__(self, grid: TYPE_INPUT_VALUE = None, iterations: TYPE_INPUT_INT = 1):
|
|
777
|
+
super().__init__()
|
|
778
|
+
key_args = {"Grid": grid, "Iterations": iterations}
|
|
779
|
+
self._establish_links(**key_args)
|
|
780
|
+
|
|
781
|
+
@property
|
|
782
|
+
def i_grid(self) -> SocketLinker:
|
|
783
|
+
"""Input socket: Grid"""
|
|
784
|
+
return self._input("Grid")
|
|
785
|
+
|
|
786
|
+
@property
|
|
787
|
+
def i_iterations(self) -> SocketLinker:
|
|
788
|
+
"""Input socket: Iterations"""
|
|
789
|
+
return self._input("Iterations")
|
|
790
|
+
|
|
791
|
+
@property
|
|
792
|
+
def o_grid(self) -> SocketLinker:
|
|
793
|
+
"""Output socket: Grid"""
|
|
794
|
+
return self._output("Grid")
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
class SDFGridMean(NodeBuilder):
|
|
798
|
+
"""Apply mean (box) filter smoothing to a signed distance field. Fast separable averaging filter for general smoothing of the distance field"""
|
|
799
|
+
|
|
800
|
+
name = "GeometryNodeSDFGridMean"
|
|
801
|
+
node: bpy.types.GeometryNodeSDFGridMean
|
|
802
|
+
|
|
803
|
+
def __init__(
|
|
804
|
+
self,
|
|
805
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
806
|
+
width: TYPE_INPUT_INT = 1,
|
|
807
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
808
|
+
):
|
|
809
|
+
super().__init__()
|
|
810
|
+
key_args = {"Grid": grid, "Width": width, "Iterations": iterations}
|
|
811
|
+
self._establish_links(**key_args)
|
|
812
|
+
|
|
813
|
+
@property
|
|
814
|
+
def i_grid(self) -> SocketLinker:
|
|
815
|
+
"""Input socket: Grid"""
|
|
816
|
+
return self._input("Grid")
|
|
817
|
+
|
|
818
|
+
@property
|
|
819
|
+
def i_width(self) -> SocketLinker:
|
|
820
|
+
"""Input socket: Width"""
|
|
821
|
+
return self._input("Width")
|
|
822
|
+
|
|
823
|
+
@property
|
|
824
|
+
def i_iterations(self) -> SocketLinker:
|
|
825
|
+
"""Input socket: Iterations"""
|
|
826
|
+
return self._input("Iterations")
|
|
827
|
+
|
|
828
|
+
@property
|
|
829
|
+
def o_grid(self) -> SocketLinker:
|
|
830
|
+
"""Output socket: Grid"""
|
|
831
|
+
return self._output("Grid")
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
class SDFGridMeanCurvature(NodeBuilder):
|
|
835
|
+
"""Apply mean curvature flow smoothing to a signed distance field. Evolves the surface based on its mean curvature, naturally smoothing high-curvature regions more than flat areas"""
|
|
836
|
+
|
|
837
|
+
name = "GeometryNodeSDFGridMeanCurvature"
|
|
838
|
+
node: bpy.types.GeometryNodeSDFGridMeanCurvature
|
|
839
|
+
|
|
840
|
+
def __init__(
|
|
841
|
+
self,
|
|
842
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
843
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
844
|
+
):
|
|
845
|
+
super().__init__()
|
|
846
|
+
key_args = {"Grid": grid, "Iterations": iterations}
|
|
847
|
+
self._establish_links(**key_args)
|
|
848
|
+
|
|
849
|
+
@property
|
|
850
|
+
def i_grid(self) -> SocketLinker:
|
|
851
|
+
"""Input socket: Grid"""
|
|
852
|
+
return self._input("Grid")
|
|
853
|
+
|
|
854
|
+
@property
|
|
855
|
+
def i_iterations(self) -> SocketLinker:
|
|
856
|
+
"""Input socket: Iterations"""
|
|
857
|
+
return self._input("Iterations")
|
|
858
|
+
|
|
859
|
+
@property
|
|
860
|
+
def o_grid(self) -> SocketLinker:
|
|
861
|
+
"""Output socket: Grid"""
|
|
862
|
+
return self._output("Grid")
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
class SDFGridMedian(NodeBuilder):
|
|
866
|
+
"""Apply median filter to a signed distance field. Reduces noise while preserving sharp features and edges in the distance field"""
|
|
867
|
+
|
|
868
|
+
name = "GeometryNodeSDFGridMedian"
|
|
869
|
+
node: bpy.types.GeometryNodeSDFGridMedian
|
|
870
|
+
|
|
871
|
+
def __init__(
|
|
872
|
+
self,
|
|
873
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
874
|
+
width: TYPE_INPUT_INT = 1,
|
|
875
|
+
iterations: TYPE_INPUT_INT = 1,
|
|
876
|
+
):
|
|
877
|
+
super().__init__()
|
|
878
|
+
key_args = {"Grid": grid, "Width": width, "Iterations": iterations}
|
|
879
|
+
self._establish_links(**key_args)
|
|
880
|
+
|
|
881
|
+
@property
|
|
882
|
+
def i_grid(self) -> SocketLinker:
|
|
883
|
+
"""Input socket: Grid"""
|
|
884
|
+
return self._input("Grid")
|
|
885
|
+
|
|
886
|
+
@property
|
|
887
|
+
def i_width(self) -> SocketLinker:
|
|
888
|
+
"""Input socket: Width"""
|
|
889
|
+
return self._input("Width")
|
|
890
|
+
|
|
891
|
+
@property
|
|
892
|
+
def i_iterations(self) -> SocketLinker:
|
|
893
|
+
"""Input socket: Iterations"""
|
|
894
|
+
return self._input("Iterations")
|
|
895
|
+
|
|
896
|
+
@property
|
|
897
|
+
def o_grid(self) -> SocketLinker:
|
|
898
|
+
"""Output socket: Grid"""
|
|
899
|
+
return self._output("Grid")
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
class SDFGridOffset(NodeBuilder):
|
|
903
|
+
"""Offset a signed distance field surface by a world-space distance. Dilates (positive) or erodes (negative) while maintaining the signed distance property"""
|
|
904
|
+
|
|
905
|
+
name = "GeometryNodeSDFGridOffset"
|
|
906
|
+
node: bpy.types.GeometryNodeSDFGridOffset
|
|
907
|
+
|
|
908
|
+
def __init__(self, grid: TYPE_INPUT_VALUE = 0.0, distance: TYPE_INPUT_VALUE = 0.1):
|
|
909
|
+
super().__init__()
|
|
910
|
+
key_args = {"Grid": grid, "Distance": distance}
|
|
911
|
+
self._establish_links(**key_args)
|
|
912
|
+
|
|
913
|
+
@property
|
|
914
|
+
def i_grid(self) -> SocketLinker:
|
|
915
|
+
"""Input socket: Grid"""
|
|
916
|
+
return self._input("Grid")
|
|
917
|
+
|
|
918
|
+
@property
|
|
919
|
+
def i_distance(self) -> SocketLinker:
|
|
920
|
+
"""Input socket: Distance"""
|
|
921
|
+
return self._input("Distance")
|
|
922
|
+
|
|
923
|
+
@property
|
|
924
|
+
def o_grid(self) -> SocketLinker:
|
|
925
|
+
"""Output socket: Grid"""
|
|
926
|
+
return self._output("Grid")
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
class SampleGrid(NodeBuilder):
|
|
930
|
+
"""Retrieve values from the specified volume grid"""
|
|
931
|
+
|
|
932
|
+
name = "GeometryNodeSampleGrid"
|
|
933
|
+
node: bpy.types.GeometryNodeSampleGrid
|
|
934
|
+
|
|
935
|
+
def __init__(
|
|
936
|
+
self,
|
|
937
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
938
|
+
position: TYPE_INPUT_VECTOR = None,
|
|
939
|
+
interpolation: Literal["Trilinear", "Triquadratic", "Nearest Neighbor"]
|
|
940
|
+
| bpy.types.NodeSocketMenu = "Trilinear",
|
|
941
|
+
*,
|
|
942
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
943
|
+
):
|
|
944
|
+
super().__init__()
|
|
945
|
+
key_args = {"Grid": grid, "Position": position, "Interpolation": interpolation}
|
|
946
|
+
self.data_type = data_type
|
|
947
|
+
self._establish_links(**key_args)
|
|
948
|
+
|
|
949
|
+
@property
|
|
950
|
+
def i_grid(self) -> SocketLinker:
|
|
951
|
+
"""Input socket: Grid"""
|
|
952
|
+
return self._input("Grid")
|
|
953
|
+
|
|
954
|
+
@property
|
|
955
|
+
def i_position(self) -> SocketLinker:
|
|
956
|
+
"""Input socket: Position"""
|
|
957
|
+
return self._input("Position")
|
|
958
|
+
|
|
959
|
+
@property
|
|
960
|
+
def i_interpolation(self) -> SocketLinker:
|
|
961
|
+
"""Input socket: Interpolation"""
|
|
962
|
+
return self._input("Interpolation")
|
|
963
|
+
|
|
964
|
+
@property
|
|
965
|
+
def o_value(self) -> SocketLinker:
|
|
966
|
+
"""Output socket: Value"""
|
|
967
|
+
return self._output("Value")
|
|
968
|
+
|
|
969
|
+
@property
|
|
970
|
+
def data_type(
|
|
971
|
+
self,
|
|
972
|
+
) -> _GridDataTypes:
|
|
973
|
+
return self.node.data_type # type: ignore
|
|
974
|
+
|
|
975
|
+
@data_type.setter
|
|
976
|
+
def data_type(
|
|
977
|
+
self,
|
|
978
|
+
value: _GridDataTypes,
|
|
979
|
+
):
|
|
980
|
+
self.node.data_type = value
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
class SampleGridIndex(NodeBuilder):
|
|
984
|
+
"""Retrieve volume grid values at specific voxels"""
|
|
985
|
+
|
|
986
|
+
name = "GeometryNodeSampleGridIndex"
|
|
987
|
+
node: bpy.types.GeometryNodeSampleGridIndex
|
|
988
|
+
|
|
989
|
+
def __init__(
|
|
990
|
+
self,
|
|
991
|
+
grid: TYPE_INPUT_VALUE = None,
|
|
992
|
+
x: TYPE_INPUT_INT = 0,
|
|
993
|
+
y: TYPE_INPUT_INT = 0,
|
|
994
|
+
z: TYPE_INPUT_INT = 0,
|
|
995
|
+
*,
|
|
996
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
997
|
+
):
|
|
998
|
+
super().__init__()
|
|
999
|
+
key_args = {"Grid": grid, "X": x, "Y": y, "Z": z}
|
|
1000
|
+
self.data_type = data_type
|
|
1001
|
+
self._establish_links(**key_args)
|
|
1002
|
+
|
|
1003
|
+
@property
|
|
1004
|
+
def i_grid(self) -> SocketLinker:
|
|
1005
|
+
"""Input socket: Grid"""
|
|
1006
|
+
return self._input("Grid")
|
|
1007
|
+
|
|
1008
|
+
@property
|
|
1009
|
+
def i_x(self) -> SocketLinker:
|
|
1010
|
+
"""Input socket: X"""
|
|
1011
|
+
return self._input("X")
|
|
1012
|
+
|
|
1013
|
+
@property
|
|
1014
|
+
def i_y(self) -> SocketLinker:
|
|
1015
|
+
"""Input socket: Y"""
|
|
1016
|
+
return self._input("Y")
|
|
1017
|
+
|
|
1018
|
+
@property
|
|
1019
|
+
def i_z(self) -> SocketLinker:
|
|
1020
|
+
"""Input socket: Z"""
|
|
1021
|
+
return self._input("Z")
|
|
1022
|
+
|
|
1023
|
+
@property
|
|
1024
|
+
def o_value(self) -> SocketLinker:
|
|
1025
|
+
"""Output socket: Value"""
|
|
1026
|
+
return self._output("Value")
|
|
1027
|
+
|
|
1028
|
+
@property
|
|
1029
|
+
def data_type(
|
|
1030
|
+
self,
|
|
1031
|
+
) -> _GridDataTypes:
|
|
1032
|
+
return self.node.data_type # type: ignore
|
|
1033
|
+
|
|
1034
|
+
@data_type.setter
|
|
1035
|
+
def data_type(
|
|
1036
|
+
self,
|
|
1037
|
+
value: _GridDataTypes,
|
|
1038
|
+
):
|
|
1039
|
+
self.node.data_type = value
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
class SetGridBackground(NodeBuilder):
|
|
1043
|
+
"""Set the background value used for inactive voxels and tiles"""
|
|
1044
|
+
|
|
1045
|
+
name = "GeometryNodeSetGridBackground"
|
|
1046
|
+
node: bpy.types.GeometryNodeSetGridBackground
|
|
1047
|
+
|
|
1048
|
+
def __init__(
|
|
1049
|
+
self,
|
|
1050
|
+
grid: TYPE_INPUT_VALUE = 0.0,
|
|
1051
|
+
background: TYPE_INPUT_VALUE = 0.0,
|
|
1052
|
+
*,
|
|
1053
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
1054
|
+
):
|
|
1055
|
+
super().__init__()
|
|
1056
|
+
key_args = {"Grid": grid, "Background": background}
|
|
1057
|
+
self.data_type = data_type
|
|
1058
|
+
self._establish_links(**key_args)
|
|
1059
|
+
|
|
1060
|
+
@property
|
|
1061
|
+
def i_grid(self) -> SocketLinker:
|
|
1062
|
+
"""Input socket: Grid"""
|
|
1063
|
+
return self._input("Grid")
|
|
1064
|
+
|
|
1065
|
+
@property
|
|
1066
|
+
def i_background(self) -> SocketLinker:
|
|
1067
|
+
"""Input socket: Background"""
|
|
1068
|
+
return self._input("Background")
|
|
1069
|
+
|
|
1070
|
+
@property
|
|
1071
|
+
def o_grid(self) -> SocketLinker:
|
|
1072
|
+
"""Output socket: Grid"""
|
|
1073
|
+
return self._output("Grid")
|
|
1074
|
+
|
|
1075
|
+
@property
|
|
1076
|
+
def data_type(
|
|
1077
|
+
self,
|
|
1078
|
+
) -> _GridDataTypes:
|
|
1079
|
+
return self.node.data_type # type: ignore
|
|
1080
|
+
|
|
1081
|
+
@data_type.setter
|
|
1082
|
+
def data_type(
|
|
1083
|
+
self,
|
|
1084
|
+
value: _GridDataTypes,
|
|
1085
|
+
):
|
|
1086
|
+
self.node.data_type = value
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
class SetGridTransform(NodeBuilder):
|
|
1090
|
+
"""Set the transform for the grid from index space into object space."""
|
|
1091
|
+
|
|
1092
|
+
name = "GeometryNodeSetGridTransform"
|
|
1093
|
+
node: bpy.types.GeometryNodeSetGridTransform
|
|
1094
|
+
|
|
1095
|
+
def __init__(
|
|
1096
|
+
self,
|
|
1097
|
+
grid: TYPE_INPUT_VALUE = 0.0,
|
|
1098
|
+
transform: LINKABLE | None = None,
|
|
1099
|
+
*,
|
|
1100
|
+
data_type: _GridDataTypes = "FLOAT",
|
|
1101
|
+
):
|
|
1102
|
+
super().__init__()
|
|
1103
|
+
key_args = {"Grid": grid, "Transform": transform}
|
|
1104
|
+
self.data_type = data_type
|
|
1105
|
+
self._establish_links(**key_args)
|
|
1106
|
+
|
|
1107
|
+
@property
|
|
1108
|
+
def i_grid(self) -> SocketLinker:
|
|
1109
|
+
"""Input socket: Grid"""
|
|
1110
|
+
return self._input("Grid")
|
|
1111
|
+
|
|
1112
|
+
@property
|
|
1113
|
+
def i_transform(self) -> SocketLinker:
|
|
1114
|
+
"""Input socket: Transform"""
|
|
1115
|
+
return self._input("Transform")
|
|
1116
|
+
|
|
1117
|
+
@property
|
|
1118
|
+
def o_is_valid(self) -> SocketLinker:
|
|
1119
|
+
"""Output socket: Is Valid"""
|
|
1120
|
+
return self._output("Is Valid")
|
|
1121
|
+
|
|
1122
|
+
@property
|
|
1123
|
+
def o_grid(self) -> SocketLinker:
|
|
1124
|
+
"""Output socket: Grid"""
|
|
1125
|
+
return self._output("Grid")
|
|
1126
|
+
|
|
1127
|
+
@property
|
|
1128
|
+
def data_type(
|
|
1129
|
+
self,
|
|
1130
|
+
) -> _GridDataTypes:
|
|
1131
|
+
return self.node.data_type # type: ignore
|
|
1132
|
+
|
|
1133
|
+
@data_type.setter
|
|
1134
|
+
def data_type(
|
|
1135
|
+
self,
|
|
1136
|
+
value: _GridDataTypes,
|
|
1137
|
+
):
|
|
1138
|
+
self.node.data_type = value
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
class StoreNamedGrid(NodeBuilder):
|
|
1142
|
+
"""Store grid data in a volume geometry with the specified name"""
|
|
1143
|
+
|
|
1144
|
+
name = "GeometryNodeStoreNamedGrid"
|
|
1145
|
+
node: bpy.types.GeometryNodeStoreNamedGrid
|
|
1146
|
+
|
|
1147
|
+
def __init__(
|
|
1148
|
+
self,
|
|
1149
|
+
volume: TYPE_INPUT_GEOMETRY = None,
|
|
1150
|
+
name: TYPE_INPUT_STRING = "",
|
|
1151
|
+
grid: TYPE_INPUT_VALUE = 0.0,
|
|
1152
|
+
*,
|
|
1153
|
+
data_type: Literal["FLOAT", "VECTOR_FLOAT", "INT", "BOOLEAN"] = "FLOAT",
|
|
1154
|
+
):
|
|
1155
|
+
super().__init__()
|
|
1156
|
+
key_args = {"Volume": volume, "Name": name, "Grid": grid}
|
|
1157
|
+
self.data_type = data_type
|
|
1158
|
+
self._establish_links(**key_args)
|
|
1159
|
+
|
|
1160
|
+
@property
|
|
1161
|
+
def i_volume(self) -> SocketLinker:
|
|
1162
|
+
"""Input socket: Volume"""
|
|
1163
|
+
return self._input("Volume")
|
|
1164
|
+
|
|
1165
|
+
@property
|
|
1166
|
+
def i_name(self) -> SocketLinker:
|
|
1167
|
+
"""Input socket: Name"""
|
|
1168
|
+
return self._input("Name")
|
|
1169
|
+
|
|
1170
|
+
@property
|
|
1171
|
+
def i_grid(self) -> SocketLinker:
|
|
1172
|
+
"""Input socket: Grid"""
|
|
1173
|
+
return self._input("Grid")
|
|
1174
|
+
|
|
1175
|
+
@property
|
|
1176
|
+
def o_volume(self) -> SocketLinker:
|
|
1177
|
+
"""Output socket: Volume"""
|
|
1178
|
+
return self._output("Volume")
|
|
1179
|
+
|
|
1180
|
+
@property
|
|
1181
|
+
def data_type(
|
|
1182
|
+
self,
|
|
1183
|
+
) -> Literal["FLOAT", "VECTOR_FLOAT", "INT", "BOOLEAN"]:
|
|
1184
|
+
return self.node.data_type # type: ignore
|
|
1185
|
+
|
|
1186
|
+
@data_type.setter
|
|
1187
|
+
def data_type(
|
|
1188
|
+
self,
|
|
1189
|
+
value: Literal["FLOAT", "VECTOR_FLOAT", "INT", "BOOLEAN"],
|
|
1190
|
+
):
|
|
1191
|
+
self.node.data_type = value
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
class GridToMesh(NodeBuilder):
|
|
1195
|
+
"""Generate a mesh on the "surface" of a volume grid"""
|
|
1196
|
+
|
|
1197
|
+
name = "GeometryNodeGridToMesh"
|
|
1198
|
+
node: bpy.types.GeometryNodeGridToMesh
|
|
1199
|
+
|
|
1200
|
+
def __init__(
|
|
1201
|
+
self,
|
|
1202
|
+
grid: TYPE_INPUT_VALUE = 0.0,
|
|
1203
|
+
threshold: TYPE_INPUT_VALUE = 0.1,
|
|
1204
|
+
adaptivity: TYPE_INPUT_VALUE = 0.0,
|
|
1205
|
+
):
|
|
1206
|
+
super().__init__()
|
|
1207
|
+
key_args = {"Grid": grid, "Threshold": threshold, "Adaptivity": adaptivity}
|
|
1208
|
+
self._establish_links(**key_args)
|
|
1209
|
+
|
|
1210
|
+
@property
|
|
1211
|
+
def i_grid(self) -> SocketLinker:
|
|
1212
|
+
"""Input socket: Grid"""
|
|
1213
|
+
return self._input("Grid")
|
|
1214
|
+
|
|
1215
|
+
@property
|
|
1216
|
+
def i_threshold(self) -> SocketLinker:
|
|
1217
|
+
"""Input socket: Threshold"""
|
|
1218
|
+
return self._input("Threshold")
|
|
1219
|
+
|
|
1220
|
+
@property
|
|
1221
|
+
def i_adaptivity(self) -> SocketLinker:
|
|
1222
|
+
"""Input socket: Adaptivity"""
|
|
1223
|
+
return self._input("Adaptivity")
|
|
1224
|
+
|
|
1225
|
+
@property
|
|
1226
|
+
def o_mesh(self) -> SocketLinker:
|
|
1227
|
+
"""Output socket: Mesh"""
|
|
1228
|
+
return self._output("Mesh")
|