nodebpy 0.3.0__py3-none-any.whl → 0.3.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 +37 -25
- nodebpy/nodes/__init__.py +6 -0
- nodebpy/nodes/attribute.py +98 -4
- nodebpy/nodes/color.py +6 -2
- nodebpy/nodes/converter.py +357 -54
- nodebpy/nodes/experimental.py +9 -3
- nodebpy/nodes/geometry.py +390 -94
- nodebpy/nodes/grid.py +90 -30
- nodebpy/nodes/group.py +3 -1
- nodebpy/nodes/input.py +239 -78
- nodebpy/nodes/interface.py +21 -7
- nodebpy/nodes/manual.py +6 -6
- nodebpy/nodes/output.py +8 -1
- nodebpy/nodes/texture.py +30 -10
- nodebpy/nodes/vector.py +41 -4
- nodebpy/nodes/zone.py +125 -99
- {nodebpy-0.3.0.dist-info → nodebpy-0.3.1.dist-info}/METADATA +11 -1
- nodebpy-0.3.1.dist-info/RECORD +26 -0
- nodebpy-0.3.0.dist-info/RECORD +0 -26
- {nodebpy-0.3.0.dist-info → nodebpy-0.3.1.dist-info}/WHEEL +0 -0
- {nodebpy-0.3.0.dist-info → nodebpy-0.3.1.dist-info}/entry_points.txt +0 -0
nodebpy/nodes/interface.py
CHANGED
|
@@ -14,7 +14,9 @@ from ..types import (
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class DialGizmo(NodeBuilder):
|
|
17
|
-
"""
|
|
17
|
+
"""
|
|
18
|
+
Show a dial gizmo in the viewport for a value
|
|
19
|
+
"""
|
|
18
20
|
|
|
19
21
|
_bl_idname = "GeometryNodeGizmoDial"
|
|
20
22
|
node: bpy.types.GeometryNodeGizmoDial
|
|
@@ -80,7 +82,9 @@ class DialGizmo(NodeBuilder):
|
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
class EnableOutput(NodeBuilder):
|
|
83
|
-
"""
|
|
85
|
+
"""
|
|
86
|
+
Either pass through the input value or output the fallback value
|
|
87
|
+
"""
|
|
84
88
|
|
|
85
89
|
_bl_idname = "NodeEnableOutput"
|
|
86
90
|
node: bpy.types.Node
|
|
@@ -258,7 +262,9 @@ class EnableOutput(NodeBuilder):
|
|
|
258
262
|
|
|
259
263
|
|
|
260
264
|
class GroupInput(NodeBuilder):
|
|
261
|
-
"""
|
|
265
|
+
"""
|
|
266
|
+
Expose connected data from inside a node group as inputs to its interface
|
|
267
|
+
"""
|
|
262
268
|
|
|
263
269
|
_bl_idname = "NodeGroupInput"
|
|
264
270
|
node: bpy.types.Node
|
|
@@ -271,7 +277,9 @@ class GroupInput(NodeBuilder):
|
|
|
271
277
|
|
|
272
278
|
|
|
273
279
|
class GroupOutput(NodeBuilder):
|
|
274
|
-
"""
|
|
280
|
+
"""
|
|
281
|
+
Output data from inside of a node group
|
|
282
|
+
"""
|
|
275
283
|
|
|
276
284
|
_bl_idname = "NodeGroupOutput"
|
|
277
285
|
node: bpy.types.Node
|
|
@@ -292,7 +300,9 @@ class GroupOutput(NodeBuilder):
|
|
|
292
300
|
|
|
293
301
|
|
|
294
302
|
class LinearGizmo(NodeBuilder):
|
|
295
|
-
"""
|
|
303
|
+
"""
|
|
304
|
+
Show a linear gizmo in the viewport for a value
|
|
305
|
+
"""
|
|
296
306
|
|
|
297
307
|
_bl_idname = "GeometryNodeGizmoLinear"
|
|
298
308
|
node: bpy.types.GeometryNodeGizmoLinear
|
|
@@ -350,7 +360,9 @@ class LinearGizmo(NodeBuilder):
|
|
|
350
360
|
|
|
351
361
|
|
|
352
362
|
class TransformGizmo(NodeBuilder):
|
|
353
|
-
"""
|
|
363
|
+
"""
|
|
364
|
+
Show a transform gizmo in the viewport
|
|
365
|
+
"""
|
|
354
366
|
|
|
355
367
|
_bl_idname = "GeometryNodeGizmoTransform"
|
|
356
368
|
node: bpy.types.GeometryNodeGizmoTransform
|
|
@@ -478,7 +490,9 @@ class TransformGizmo(NodeBuilder):
|
|
|
478
490
|
|
|
479
491
|
|
|
480
492
|
class Warning(NodeBuilder):
|
|
481
|
-
"""
|
|
493
|
+
"""
|
|
494
|
+
Create custom warnings in node groups
|
|
495
|
+
"""
|
|
482
496
|
|
|
483
497
|
_bl_idname = "GeometryNodeWarning"
|
|
484
498
|
node: bpy.types.GeometryNodeWarning
|
nodebpy/nodes/manual.py
CHANGED
|
@@ -35,6 +35,9 @@ from ..types import (
|
|
|
35
35
|
_is_default_value,
|
|
36
36
|
)
|
|
37
37
|
from .zone import (
|
|
38
|
+
ForEachGeometryElementInput,
|
|
39
|
+
ForEachGeometryElementOutput,
|
|
40
|
+
ForEachGeometryElementZone,
|
|
38
41
|
RepeatInput,
|
|
39
42
|
RepeatOutput,
|
|
40
43
|
RepeatZone,
|
|
@@ -50,6 +53,9 @@ __all__ = (
|
|
|
50
53
|
"SimulationInput",
|
|
51
54
|
"SimulationOutput",
|
|
52
55
|
"SimulationZone",
|
|
56
|
+
"ForEachGeometryElementInput",
|
|
57
|
+
"ForEachGeometryElementOutput",
|
|
58
|
+
"ForEachGeometryElementZone",
|
|
53
59
|
"GeometryToInstance",
|
|
54
60
|
"SDFGridBoolean",
|
|
55
61
|
#
|
|
@@ -64,12 +70,6 @@ __all__ = (
|
|
|
64
70
|
"Bake",
|
|
65
71
|
"JoinStrings",
|
|
66
72
|
"GeometryToInstance",
|
|
67
|
-
"RepeatInput",
|
|
68
|
-
"RepeatOutput",
|
|
69
|
-
"RepeatZone",
|
|
70
|
-
"SimulationInput",
|
|
71
|
-
"SimulationOutput",
|
|
72
|
-
"SimulationZone",
|
|
73
73
|
"FormatString",
|
|
74
74
|
"Value",
|
|
75
75
|
"AccumulateField",
|
nodebpy/nodes/output.py
CHANGED
|
@@ -6,7 +6,9 @@ from ..builder import NodeBuilder
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Viewer(NodeBuilder):
|
|
9
|
-
"""
|
|
9
|
+
"""
|
|
10
|
+
Display the input data in the Spreadsheet Editor
|
|
11
|
+
"""
|
|
10
12
|
|
|
11
13
|
_bl_idname = "GeometryNodeViewer"
|
|
12
14
|
node: bpy.types.GeometryNodeViewer
|
|
@@ -44,6 +46,11 @@ class Viewer(NodeBuilder):
|
|
|
44
46
|
"""Create Viewer with operation 'Face'."""
|
|
45
47
|
return cls(domain="FACE")
|
|
46
48
|
|
|
49
|
+
@classmethod
|
|
50
|
+
def face_corner(cls) -> "Viewer":
|
|
51
|
+
"""Create Viewer with operation 'Face Corner'."""
|
|
52
|
+
return cls(domain="CORNER")
|
|
53
|
+
|
|
47
54
|
@classmethod
|
|
48
55
|
def spline(cls) -> "Viewer":
|
|
49
56
|
"""Create Viewer with operation 'Spline'."""
|
nodebpy/nodes/texture.py
CHANGED
|
@@ -13,7 +13,9 @@ from ..types import (
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class BrickTexture(NodeBuilder):
|
|
16
|
-
"""
|
|
16
|
+
"""
|
|
17
|
+
Generate a procedural texture producing bricks
|
|
18
|
+
"""
|
|
17
19
|
|
|
18
20
|
_bl_idname = "ShaderNodeTexBrick"
|
|
19
21
|
node: bpy.types.ShaderNodeTexBrick
|
|
@@ -149,7 +151,9 @@ class BrickTexture(NodeBuilder):
|
|
|
149
151
|
|
|
150
152
|
|
|
151
153
|
class CheckerTexture(NodeBuilder):
|
|
152
|
-
"""
|
|
154
|
+
"""
|
|
155
|
+
Generate a checkerboard texture
|
|
156
|
+
"""
|
|
153
157
|
|
|
154
158
|
_bl_idname = "ShaderNodeTexChecker"
|
|
155
159
|
node: bpy.types.ShaderNodeTexChecker
|
|
@@ -203,7 +207,9 @@ class CheckerTexture(NodeBuilder):
|
|
|
203
207
|
|
|
204
208
|
|
|
205
209
|
class GaborTexture(NodeBuilder):
|
|
206
|
-
"""
|
|
210
|
+
"""
|
|
211
|
+
Generate Gabor noise
|
|
212
|
+
"""
|
|
207
213
|
|
|
208
214
|
_bl_idname = "ShaderNodeTexGabor"
|
|
209
215
|
node: bpy.types.ShaderNodeTexGabor
|
|
@@ -286,7 +292,9 @@ class GaborTexture(NodeBuilder):
|
|
|
286
292
|
|
|
287
293
|
|
|
288
294
|
class GradientTexture(NodeBuilder):
|
|
289
|
-
"""
|
|
295
|
+
"""
|
|
296
|
+
Generate interpolated color and intensity values based on the input vector
|
|
297
|
+
"""
|
|
290
298
|
|
|
291
299
|
_bl_idname = "ShaderNodeTexGradient"
|
|
292
300
|
node: bpy.types.ShaderNodeTexGradient
|
|
@@ -356,7 +364,9 @@ class GradientTexture(NodeBuilder):
|
|
|
356
364
|
|
|
357
365
|
|
|
358
366
|
class ImageTexture(NodeBuilder):
|
|
359
|
-
"""
|
|
367
|
+
"""
|
|
368
|
+
Sample values from an image texture
|
|
369
|
+
"""
|
|
360
370
|
|
|
361
371
|
_bl_idname = "GeometryNodeImageTexture"
|
|
362
372
|
node: bpy.types.GeometryNodeImageTexture
|
|
@@ -419,7 +429,9 @@ class ImageTexture(NodeBuilder):
|
|
|
419
429
|
|
|
420
430
|
|
|
421
431
|
class MagicTexture(NodeBuilder):
|
|
422
|
-
"""
|
|
432
|
+
"""
|
|
433
|
+
Generate a psychedelic color texture
|
|
434
|
+
"""
|
|
423
435
|
|
|
424
436
|
_bl_idname = "ShaderNodeTexMagic"
|
|
425
437
|
node: bpy.types.ShaderNodeTexMagic
|
|
@@ -472,7 +484,9 @@ class MagicTexture(NodeBuilder):
|
|
|
472
484
|
|
|
473
485
|
|
|
474
486
|
class NoiseTexture(NodeBuilder):
|
|
475
|
-
"""
|
|
487
|
+
"""
|
|
488
|
+
Generate fractal Perlin noise
|
|
489
|
+
"""
|
|
476
490
|
|
|
477
491
|
_bl_idname = "ShaderNodeTexNoise"
|
|
478
492
|
node: bpy.types.ShaderNodeTexNoise
|
|
@@ -614,7 +628,9 @@ class NoiseTexture(NodeBuilder):
|
|
|
614
628
|
|
|
615
629
|
|
|
616
630
|
class VoronoiTexture(NodeBuilder):
|
|
617
|
-
"""
|
|
631
|
+
"""
|
|
632
|
+
Generate Worley noise based on the distance to random points. Typically used to generate textures such as stones, water, or biological cells
|
|
633
|
+
"""
|
|
618
634
|
|
|
619
635
|
_bl_idname = "ShaderNodeTexVoronoi"
|
|
620
636
|
node: bpy.types.ShaderNodeTexVoronoi
|
|
@@ -769,7 +785,9 @@ class VoronoiTexture(NodeBuilder):
|
|
|
769
785
|
|
|
770
786
|
|
|
771
787
|
class WaveTexture(NodeBuilder):
|
|
772
|
-
"""
|
|
788
|
+
"""
|
|
789
|
+
Generate procedural bands or rings with noise
|
|
790
|
+
"""
|
|
773
791
|
|
|
774
792
|
_bl_idname = "ShaderNodeTexWave"
|
|
775
793
|
node: bpy.types.ShaderNodeTexWave
|
|
@@ -884,7 +902,9 @@ class WaveTexture(NodeBuilder):
|
|
|
884
902
|
|
|
885
903
|
|
|
886
904
|
class WhiteNoiseTexture(NodeBuilder):
|
|
887
|
-
"""
|
|
905
|
+
"""
|
|
906
|
+
Calculate a random value or color based on an input seed
|
|
907
|
+
"""
|
|
888
908
|
|
|
889
909
|
_bl_idname = "ShaderNodeTexWhiteNoise"
|
|
890
910
|
node: bpy.types.ShaderNodeTexWhiteNoise
|
nodebpy/nodes/vector.py
CHANGED
|
@@ -10,7 +10,9 @@ from ..types import (
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class RadialTiling(NodeBuilder):
|
|
13
|
-
"""
|
|
13
|
+
"""
|
|
14
|
+
Transform Coordinate System for Radial Tiling
|
|
15
|
+
"""
|
|
14
16
|
|
|
15
17
|
_bl_idname = "ShaderNodeRadialTiling"
|
|
16
18
|
node: bpy.types.ShaderNodeRadialTiling
|
|
@@ -73,7 +75,9 @@ class RadialTiling(NodeBuilder):
|
|
|
73
75
|
|
|
74
76
|
|
|
75
77
|
class VectorCurves(NodeBuilder):
|
|
76
|
-
"""
|
|
78
|
+
"""
|
|
79
|
+
Map input vector components with curves
|
|
80
|
+
"""
|
|
77
81
|
|
|
78
82
|
_bl_idname = "ShaderNodeVectorCurve"
|
|
79
83
|
node: bpy.types.ShaderNodeVectorCurve
|
|
@@ -105,7 +109,9 @@ class VectorCurves(NodeBuilder):
|
|
|
105
109
|
|
|
106
110
|
|
|
107
111
|
class VectorMath(NodeBuilder):
|
|
108
|
-
"""
|
|
112
|
+
"""
|
|
113
|
+
Perform vector math operation
|
|
114
|
+
"""
|
|
109
115
|
|
|
110
116
|
_bl_idname = "ShaderNodeVectorMath"
|
|
111
117
|
node: bpy.types.ShaderNodeVectorMath
|
|
@@ -187,6 +193,28 @@ class VectorMath(NodeBuilder):
|
|
|
187
193
|
"""Create Vector Math with operation 'Divide'."""
|
|
188
194
|
return cls(operation="DIVIDE", vector=vector, vector_001=vector_001)
|
|
189
195
|
|
|
196
|
+
@classmethod
|
|
197
|
+
def multiply_add(
|
|
198
|
+
cls,
|
|
199
|
+
vector: TYPE_INPUT_VECTOR = None,
|
|
200
|
+
vector_001: TYPE_INPUT_VECTOR = None,
|
|
201
|
+
vector_002: TYPE_INPUT_VECTOR = None,
|
|
202
|
+
) -> "VectorMath":
|
|
203
|
+
"""Create Vector Math with operation 'Multiply Add'."""
|
|
204
|
+
return cls(
|
|
205
|
+
operation="MULTIPLY_ADD",
|
|
206
|
+
vector=vector,
|
|
207
|
+
vector_001=vector_001,
|
|
208
|
+
vector_002=vector_002,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
@classmethod
|
|
212
|
+
def cross_product(
|
|
213
|
+
cls, vector: TYPE_INPUT_VECTOR = None, vector_001: TYPE_INPUT_VECTOR = None
|
|
214
|
+
) -> "VectorMath":
|
|
215
|
+
"""Create Vector Math with operation 'Cross Product'."""
|
|
216
|
+
return cls(operation="CROSS_PRODUCT", vector=vector, vector_001=vector_001)
|
|
217
|
+
|
|
190
218
|
@classmethod
|
|
191
219
|
def project(
|
|
192
220
|
cls, vector: TYPE_INPUT_VECTOR = None, vector_001: TYPE_INPUT_VECTOR = None
|
|
@@ -228,6 +256,13 @@ class VectorMath(NodeBuilder):
|
|
|
228
256
|
vector_002=vector_002,
|
|
229
257
|
)
|
|
230
258
|
|
|
259
|
+
@classmethod
|
|
260
|
+
def dot_product(
|
|
261
|
+
cls, vector: TYPE_INPUT_VECTOR = None, vector_001: TYPE_INPUT_VECTOR = None
|
|
262
|
+
) -> "VectorMath":
|
|
263
|
+
"""Create Vector Math with operation 'Dot Product'."""
|
|
264
|
+
return cls(operation="DOT_PRODUCT", vector=vector, vector_001=vector_001)
|
|
265
|
+
|
|
231
266
|
@classmethod
|
|
232
267
|
def distance(
|
|
233
268
|
cls, vector: TYPE_INPUT_VECTOR = None, vector_001: TYPE_INPUT_VECTOR = None
|
|
@@ -447,7 +482,9 @@ class VectorMath(NodeBuilder):
|
|
|
447
482
|
|
|
448
483
|
|
|
449
484
|
class VectorRotate(NodeBuilder):
|
|
450
|
-
"""
|
|
485
|
+
"""
|
|
486
|
+
Rotate a vector around a pivot point (center)
|
|
487
|
+
"""
|
|
451
488
|
|
|
452
489
|
_bl_idname = "ShaderNodeVectorRotate"
|
|
453
490
|
node: bpy.types.ShaderNodeVectorRotate
|
nodebpy/nodes/zone.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Iterable
|
|
3
3
|
|
|
4
4
|
import bpy
|
|
5
5
|
|
|
@@ -16,8 +16,6 @@ from ..types import (
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class BaseZone(DynamicInputsMixin, NodeBuilder, ABC):
|
|
19
|
-
_items_attribute: Literal["state_items", "repeat_items"]
|
|
20
|
-
|
|
21
19
|
@property
|
|
22
20
|
@abstractmethod
|
|
23
21
|
def _items_node(
|
|
@@ -72,7 +70,11 @@ class BaseZoneInput(BaseZone, NodeBuilder, ABC):
|
|
|
72
70
|
@property
|
|
73
71
|
def output(
|
|
74
72
|
self,
|
|
75
|
-
) ->
|
|
73
|
+
) -> (
|
|
74
|
+
bpy.types.GeometryNodeSimulationOutput
|
|
75
|
+
| bpy.types.GeometryNodeRepeatOutput
|
|
76
|
+
| bpy.types.GeometryNodeForeachGeometryElementOutput
|
|
77
|
+
):
|
|
76
78
|
return self.node.paired_output # type: ignore
|
|
77
79
|
|
|
78
80
|
def _add_socket(self, name: str, type: _BakeDataTypes):
|
|
@@ -99,7 +101,6 @@ class BaseZoneOutput(BaseZone, NodeBuilder, ABC):
|
|
|
99
101
|
|
|
100
102
|
|
|
101
103
|
class BaseSimulationZone(BaseZone):
|
|
102
|
-
_items_attribute = "state_items"
|
|
103
104
|
_socket_data_types = (
|
|
104
105
|
"VALUE",
|
|
105
106
|
"INT",
|
|
@@ -168,7 +169,6 @@ class SimulationZone:
|
|
|
168
169
|
|
|
169
170
|
|
|
170
171
|
class BaseRepeatZone(BaseZone):
|
|
171
|
-
_items_attribute = "repeat_items"
|
|
172
172
|
_socket_data_types = (
|
|
173
173
|
"FLOAT",
|
|
174
174
|
"INT",
|
|
@@ -208,12 +208,6 @@ class RepeatInput(BaseRepeatZone, BaseZoneInput):
|
|
|
208
208
|
"""Output socket: Iteration"""
|
|
209
209
|
return self._output("Iteration")
|
|
210
210
|
|
|
211
|
-
@property
|
|
212
|
-
def output_node(self) -> bpy.types.GeometryNodeRepeatOutput:
|
|
213
|
-
zone_output = self.node.paired_output # type: ignore
|
|
214
|
-
assert zone_output is not None
|
|
215
|
-
return zone_output # type: ignore
|
|
216
|
-
|
|
217
211
|
|
|
218
212
|
class RepeatOutput(BaseRepeatZone, BaseZoneOutput):
|
|
219
213
|
"""Repeat Output node"""
|
|
@@ -253,25 +247,78 @@ class RepeatZone:
|
|
|
253
247
|
return self.i, self.input, self.output
|
|
254
248
|
|
|
255
249
|
|
|
256
|
-
class
|
|
250
|
+
class ForEachGeometryElementZone:
|
|
251
|
+
def __init__(
|
|
252
|
+
self,
|
|
253
|
+
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
254
|
+
selection: TYPE_INPUT_BOOLEAN = True,
|
|
255
|
+
*,
|
|
256
|
+
domain: _AttributeDomains = "POINT",
|
|
257
|
+
):
|
|
258
|
+
self.input = ForEachGeometryElementInput()
|
|
259
|
+
self.output = ForEachGeometryElementOutput()
|
|
260
|
+
self.input.node.pair_with_output(self.output.node)
|
|
261
|
+
self.output.domain = domain
|
|
262
|
+
self.input._establish_links(Geometry=geometry, Selection=selection)
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def index(self) -> SocketLinker:
|
|
266
|
+
return self.input.o_index
|
|
267
|
+
|
|
268
|
+
def __getitem__(self, index: int):
|
|
269
|
+
match index:
|
|
270
|
+
case 0:
|
|
271
|
+
return self.input
|
|
272
|
+
case 1:
|
|
273
|
+
return self.output
|
|
274
|
+
case _:
|
|
275
|
+
raise IndexError("ForEachZone has only two items")
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class ForEachGeometryElementInput(BaseZoneInput):
|
|
257
279
|
"""For Each Geometry Element Input node"""
|
|
258
280
|
|
|
281
|
+
_socket_data_types = (
|
|
282
|
+
"VALUE",
|
|
283
|
+
"INT",
|
|
284
|
+
"BOOLEAN",
|
|
285
|
+
"VECTOR",
|
|
286
|
+
"RGBA",
|
|
287
|
+
"ROTATION",
|
|
288
|
+
"MATRIX",
|
|
289
|
+
"MENU",
|
|
290
|
+
)
|
|
291
|
+
_type_map = {"VALUE": "FLOAT"}
|
|
292
|
+
|
|
259
293
|
_bl_idname = "GeometryNodeForeachGeometryElementInput"
|
|
260
294
|
node: bpy.types.GeometryNodeForeachGeometryElementInput
|
|
261
295
|
|
|
262
296
|
def __init__(
|
|
263
|
-
self,
|
|
264
|
-
geometry: TYPE_INPUT_GEOMETRY = None,
|
|
265
|
-
selection: TYPE_INPUT_BOOLEAN = True,
|
|
266
|
-
extend: LINKABLE | None = None,
|
|
267
|
-
**kwargs,
|
|
297
|
+
self, geometry: TYPE_INPUT_GEOMETRY = None, selection: TYPE_INPUT_BOOLEAN = True
|
|
268
298
|
):
|
|
269
299
|
super().__init__()
|
|
270
|
-
key_args = {"Geometry": geometry, "Selection": selection
|
|
271
|
-
key_args.update(kwargs)
|
|
272
|
-
|
|
300
|
+
key_args = {"Geometry": geometry, "Selection": selection}
|
|
273
301
|
self._establish_links(**key_args)
|
|
274
302
|
|
|
303
|
+
def capture(
|
|
304
|
+
self, value: LINKABLE, domain: _AttributeDomains = "POINT"
|
|
305
|
+
) -> SocketLinker:
|
|
306
|
+
"""Capture something as an input to the simulation"""
|
|
307
|
+
item_dict = self._add_inputs(value)
|
|
308
|
+
self._establish_links(**item_dict)
|
|
309
|
+
new_output_idx = [o.identifier for o in self.node.outputs].index(
|
|
310
|
+
"__extend__"
|
|
311
|
+
) - 1
|
|
312
|
+
print(f"{new_output_idx=}")
|
|
313
|
+
output = self.node.outputs[new_output_idx]
|
|
314
|
+
print(f"{output=} {output.type=}")
|
|
315
|
+
|
|
316
|
+
return SocketLinker(output)
|
|
317
|
+
|
|
318
|
+
@property
|
|
319
|
+
def items(self) -> bpy.types.NodeGeometryForeachGeometryElementInputItems:
|
|
320
|
+
return self.output.input_items
|
|
321
|
+
|
|
275
322
|
@property
|
|
276
323
|
def i_geometry(self) -> SocketLinker:
|
|
277
324
|
"""Input socket: Geometry"""
|
|
@@ -282,113 +329,100 @@ class ForEachGeometryElementInput(NodeBuilder):
|
|
|
282
329
|
"""Input socket: Selection"""
|
|
283
330
|
return self._input("Selection")
|
|
284
331
|
|
|
285
|
-
@property
|
|
286
|
-
def i_input_socket(self) -> SocketLinker:
|
|
287
|
-
"""Input socket:"""
|
|
288
|
-
return self._input("__extend__")
|
|
289
|
-
|
|
290
332
|
@property
|
|
291
333
|
def o_index(self) -> SocketLinker:
|
|
292
334
|
"""Output socket: Index"""
|
|
293
335
|
return self._output("Index")
|
|
294
336
|
|
|
295
|
-
@property
|
|
296
|
-
def o_input_socket(self) -> SocketLinker:
|
|
297
|
-
"""Output socket:"""
|
|
298
|
-
return self._output("__extend__")
|
|
299
|
-
|
|
300
337
|
|
|
301
|
-
class ForEachGeometryElementOutput(
|
|
338
|
+
class ForEachGeometryElementOutput(BaseZoneOutput):
|
|
302
339
|
"""For Each Geometry Element Output node"""
|
|
303
340
|
|
|
341
|
+
_socket_data_types = [
|
|
342
|
+
"VALUE",
|
|
343
|
+
"INT",
|
|
344
|
+
"BOOLEAN",
|
|
345
|
+
"VECTOR",
|
|
346
|
+
"RGBA",
|
|
347
|
+
"ROTATION",
|
|
348
|
+
"MATRIX",
|
|
349
|
+
]
|
|
350
|
+
_type_map = {"VALUE": "FLOAT"}
|
|
351
|
+
|
|
304
352
|
_bl_idname = "GeometryNodeForeachGeometryElementOutput"
|
|
305
353
|
node: bpy.types.GeometryNodeForeachGeometryElementOutput
|
|
306
354
|
|
|
307
355
|
def __init__(
|
|
308
356
|
self,
|
|
309
|
-
extend_main: LINKABLE | None = None,
|
|
310
|
-
generation_0: LINKABLE = None,
|
|
311
|
-
extend_generation: LINKABLE | None = None,
|
|
312
|
-
active_input_index: int = 0,
|
|
313
|
-
active_generation_index: int = 0,
|
|
314
|
-
active_main_index: int = 0,
|
|
315
357
|
domain: _AttributeDomains = "POINT",
|
|
316
|
-
inspection_index: int = 0,
|
|
317
358
|
**kwargs,
|
|
318
359
|
):
|
|
319
360
|
super().__init__()
|
|
320
|
-
key_args = {
|
|
321
|
-
"__extend__main": extend_main,
|
|
322
|
-
"Generation_0": generation_0,
|
|
323
|
-
"__extend__generation": extend_generation,
|
|
324
|
-
}
|
|
361
|
+
key_args = {}
|
|
325
362
|
key_args.update(kwargs)
|
|
326
|
-
self.active_input_index = active_input_index
|
|
327
|
-
self.active_generation_index = active_generation_index
|
|
328
|
-
self.active_main_index = active_main_index
|
|
329
363
|
self.domain = domain
|
|
330
|
-
self.inspection_index = inspection_index
|
|
331
364
|
self._establish_links(**key_args)
|
|
332
365
|
|
|
333
366
|
@property
|
|
334
|
-
def
|
|
335
|
-
|
|
336
|
-
|
|
367
|
+
def items(self) -> bpy.types.NodeGeometryForeachGeometryElementMainItems:
|
|
368
|
+
return self.node.main_items
|
|
369
|
+
|
|
370
|
+
@property
|
|
371
|
+
def items_generated(
|
|
372
|
+
self,
|
|
373
|
+
) -> bpy.types.NodeGeometryForeachGeometryElementGenerationItems:
|
|
374
|
+
return self.node.generation_items
|
|
375
|
+
|
|
376
|
+
def _latest(
|
|
377
|
+
self, suffix: str, sockets: Iterable[bpy.types.NodeSocket]
|
|
378
|
+
) -> bpy.types.NodeSocket:
|
|
379
|
+
idx = [o.identifier for o in sockets].index(f"__extend__{suffix}") - 1
|
|
380
|
+
return sockets[idx]
|
|
381
|
+
|
|
382
|
+
def capture(
|
|
383
|
+
self, value: LINKABLE, domain: _AttributeDomains = "POINT"
|
|
384
|
+
) -> SocketLinker:
|
|
385
|
+
"""Capture something as an input to the simulation"""
|
|
386
|
+
item_dict = self._add_inputs(value)
|
|
387
|
+
self._establish_links(**item_dict)
|
|
388
|
+
return SocketLinker(self._latest("main", self.node.outputs))
|
|
389
|
+
|
|
390
|
+
def capture_generated(self, value: LINKABLE) -> SocketLinker:
|
|
391
|
+
self._socket_data_types = self._socket_data_types + ["GEOMETRY"]
|
|
392
|
+
self._add_socket = self._add_socket_generated
|
|
393
|
+
item_dict = self._add_inputs(value)
|
|
394
|
+
self._establish_links(**item_dict)
|
|
395
|
+
self._socket_data_types = list(
|
|
396
|
+
[x for x in self._socket_data_types if x != "GEOMETRY"]
|
|
397
|
+
)
|
|
398
|
+
self._add_socket = self._add_socket_main
|
|
399
|
+
return SocketLinker(self._latest("generation", self.node.outputs))
|
|
400
|
+
|
|
401
|
+
def _add_socket_main(self, name: str, type: _BakeDataTypes):
|
|
402
|
+
"""Add a socket to the zone"""
|
|
403
|
+
_ = self.items.new(type, name)
|
|
404
|
+
return self._latest("main", self.node.inputs)
|
|
405
|
+
|
|
406
|
+
def _add_socket_generated(self, name: str, type: _BakeDataTypes):
|
|
407
|
+
"""Add a socket to the zone"""
|
|
408
|
+
_ = self.items_generated.new(type, name)
|
|
409
|
+
return self._latest("generation", self.node.inputs)
|
|
337
410
|
|
|
338
411
|
@property
|
|
339
412
|
def i_geometry(self) -> SocketLinker:
|
|
340
413
|
"""Input socket: Geometry"""
|
|
341
414
|
return self._input("Generation_0")
|
|
342
415
|
|
|
343
|
-
@property
|
|
344
|
-
def i_extend_generation(self) -> SocketLinker:
|
|
345
|
-
"""Input socket:"""
|
|
346
|
-
return self._input("__extend__generation")
|
|
347
|
-
|
|
348
416
|
@property
|
|
349
417
|
def o_geometry(self) -> SocketLinker:
|
|
350
418
|
"""Output socket: Geometry"""
|
|
351
419
|
return self._output("Geometry")
|
|
352
420
|
|
|
353
421
|
@property
|
|
354
|
-
def
|
|
355
|
-
"""Output socket:"""
|
|
356
|
-
return self._output("__extend__main")
|
|
357
|
-
|
|
358
|
-
@property
|
|
359
|
-
def o_generation_0(self) -> SocketLinker:
|
|
422
|
+
def o_generation(self) -> SocketLinker:
|
|
360
423
|
"""Output socket: Geometry"""
|
|
361
424
|
return self._output("Generation_0")
|
|
362
425
|
|
|
363
|
-
@property
|
|
364
|
-
def o_extend_generation(self) -> SocketLinker:
|
|
365
|
-
"""Output socket:"""
|
|
366
|
-
return self._output("__extend__generation")
|
|
367
|
-
|
|
368
|
-
@property
|
|
369
|
-
def active_input_index(self) -> int:
|
|
370
|
-
return self.node.active_input_index
|
|
371
|
-
|
|
372
|
-
@active_input_index.setter
|
|
373
|
-
def active_input_index(self, value: int):
|
|
374
|
-
self.node.active_input_index = value
|
|
375
|
-
|
|
376
|
-
@property
|
|
377
|
-
def active_generation_index(self) -> int:
|
|
378
|
-
return self.node.active_generation_index
|
|
379
|
-
|
|
380
|
-
@active_generation_index.setter
|
|
381
|
-
def active_generation_index(self, value: int):
|
|
382
|
-
self.node.active_generation_index = value
|
|
383
|
-
|
|
384
|
-
@property
|
|
385
|
-
def active_main_index(self) -> int:
|
|
386
|
-
return self.node.active_main_index
|
|
387
|
-
|
|
388
|
-
@active_main_index.setter
|
|
389
|
-
def active_main_index(self, value: int):
|
|
390
|
-
self.node.active_main_index = value
|
|
391
|
-
|
|
392
426
|
@property
|
|
393
427
|
def domain(
|
|
394
428
|
self,
|
|
@@ -401,11 +435,3 @@ class ForEachGeometryElementOutput(NodeBuilder):
|
|
|
401
435
|
value: _AttributeDomains,
|
|
402
436
|
):
|
|
403
437
|
self.node.domain = value
|
|
404
|
-
|
|
405
|
-
@property
|
|
406
|
-
def inspection_index(self) -> int:
|
|
407
|
-
return self.node.inspection_index
|
|
408
|
-
|
|
409
|
-
@inspection_index.setter
|
|
410
|
-
def inspection_index(self, value: int):
|
|
411
|
-
self.node.inspection_index = value
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nodebpy
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Build nodes in Blender with code
|
|
5
5
|
Author: Brady Johnston
|
|
6
6
|
Author-email: Brady Johnston <brady.johnston@me.com>
|
|
@@ -158,3 +158,13 @@ actually build.
|
|
|
158
158
|
- `TransformGeometry.matrix(CombineTrasnsform(translation=(0, 0, 1))`
|
|
159
159
|
- `TransformGeoemtry.components(translation=(0, 0, 1))`
|
|
160
160
|
- `TransformGeometry(translation=(0, 0, 1))`
|
|
161
|
+
|
|
162
|
+
## Building
|
|
163
|
+
|
|
164
|
+
Most node classes are generated automatically with this. The nodes in
|
|
165
|
+
`nodes/manual.py` are currently manually specified due to varying
|
|
166
|
+
complexities of particular nodes (usually lergacy).
|
|
167
|
+
|
|
168
|
+
``` bash
|
|
169
|
+
uv run generate.py && ruff format && ruff check --fix --unsafe-fixes
|
|
170
|
+
```
|