nodebpy 0.1.1__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.
@@ -1,1382 +0,0 @@
1
- """
2
- Some of the nodes need to be manually specified because they are a bit tricky to generate automatically.
3
- """
4
-
5
- from __future__ import annotations
6
-
7
- import bpy
8
- from bpy.types import NodeSocketFloat, NodeSocketVector
9
- from typing import Iterable, Literal
10
-
11
- from ..builder import (
12
- NodeBuilder,
13
- NodeSocket,
14
- source_socket,
15
- SocketLinker,
16
- )
17
- from . import types
18
- from .types import LINKABLE, TYPE_INPUT_BOOLEAN, TYPE_INPUT_VECTOR, _AttributeDomains
19
-
20
- _RANDOM_VALUE_DATA_TYPES = Literal["FLOAT", "INT", "BOOLEAN", "FLOAT_VECTOR"]
21
-
22
-
23
- class Vector(NodeBuilder):
24
- """Provide a vector value that can be connected to other nodes in the tree"""
25
-
26
- name = "FunctionNodeInputVector"
27
- node: bpy.types.FunctionNodeInputVector
28
-
29
- def __init__(self, vector: list[float, float, float] | None = (0, 0, 0), **kwargs):
30
- super().__init__()
31
- key_args = kwargs
32
- self.vector = vector
33
- self._establish_links(**key_args)
34
-
35
- @property
36
- def o_vector(self) -> bpy.types.NodeSocketVector:
37
- """Output socket: Vector"""
38
- return self._output("Vector")
39
-
40
- @property
41
- def vector(self) -> list[float, float, float]:
42
- return self.node.vector
43
-
44
- @vector.setter
45
- def vector(self, value: list[float, float, float]):
46
- self.node.vector = value
47
-
48
-
49
- class RandomValue(NodeBuilder):
50
- """Random Value node"""
51
-
52
- name = "FunctionNodeRandomValue"
53
- node: bpy.types.FunctionNodeRandomValue
54
- _default_input_id = "ID"
55
-
56
- def __init__(
57
- self,
58
- data_type: _RANDOM_VALUE_DATA_TYPES,
59
- id: int | LINKABLE | None = None,
60
- seed: int | LINKABLE | None = None,
61
- **kwargs,
62
- ):
63
- super().__init__()
64
- self.node.data_type = data_type
65
- key_args = {
66
- "ID": id,
67
- "Seed": seed,
68
- }
69
- key_args.update(kwargs)
70
-
71
- self._establish_links(**key_args)
72
-
73
- @property
74
- def data_type(self) -> _RANDOM_VALUE_DATA_TYPES:
75
- return self.node.data_type # type: ignore
76
-
77
- @data_type.setter
78
- def data_type(self, value: _RANDOM_VALUE_DATA_TYPES):
79
- self.node.data_type = value
80
-
81
- @property
82
- def o_value(self) -> NodeSocket:
83
- """Output socket: Value"""
84
- match self.data_type:
85
- case "FLOAT":
86
- return self._output("Value_001")
87
- case "INT":
88
- return self._output("Value_002")
89
- case "BOOLEAN":
90
- return self._output("Value_003")
91
- case "FLOAT_VECTOR":
92
- return self._output("Value")
93
-
94
- def i_min(self) -> NodeSocket:
95
- """Input socket: Minimum"""
96
- match self.data_type:
97
- case "FLOAT":
98
- return self._input("Min_001")
99
- case "INT":
100
- return self._input("Min_002")
101
- case "BOOLEAN":
102
- raise ValueError(
103
- "Boolean data type does not support minimum value, use 'Probability'"
104
- )
105
- case "FLOAT_VECTOR":
106
- return self._input("Min")
107
-
108
- def i_max(self) -> NodeSocket:
109
- """Input socket: Maximum"""
110
- match self.data_type:
111
- case "FLOAT":
112
- return self._input("Max_001")
113
- case "INT":
114
- return self._input("Max_002")
115
- case "BOOLEAN":
116
- raise ValueError(
117
- "Boolean data type does not support maximum value, use 'Probability'"
118
- )
119
- case "FLOAT_VECTOR":
120
- return self._input("Max")
121
-
122
- def i_probability(self) -> NodeSocket:
123
- """Input socket: Probability"""
124
- if self.data_type != "BOOLEAN":
125
- raise ValueError(
126
- f"Probability socket is only supported for boolean data types, not for data type: {self.data_type}"
127
- )
128
-
129
- return self._input("Probability")
130
-
131
- @classmethod
132
- def float(
133
- cls,
134
- min: float | LINKABLE = 0.0,
135
- max: float | LINKABLE = 1.0,
136
- id: int | LINKABLE | None = None,
137
- seed: int | LINKABLE = 1,
138
- ) -> NodeBuilder:
139
- buidler = cls(Min_001=min, Max_001=max, id=id, seed=seed, data_type="FLOAT")
140
- buidler._default_output_id = "Value_001"
141
- return buidler
142
-
143
- @classmethod
144
- def integer(
145
- cls,
146
- min: int | LINKABLE = 0,
147
- max: int | LINKABLE = 1,
148
- id: int | LINKABLE | None = None,
149
- seed: int | LINKABLE = 1,
150
- ) -> NodeBuilder:
151
- buidler = cls(Min_002=min, Max_002=max, id=id, seed=seed, data_type="INT")
152
- buidler._default_output_id = "Value_002"
153
- return buidler
154
-
155
- @classmethod
156
- def boolean(
157
- cls,
158
- probability: float | LINKABLE = 0.5,
159
- id: int | LINKABLE | None = None,
160
- seed: int | LINKABLE = 1,
161
- ) -> NodeBuilder:
162
- builder = cls(Probability=probability, id=id, seed=seed, data_type="BOOLEAN")
163
- builder._default_output_id = "Value_003"
164
- return builder
165
-
166
- @classmethod
167
- def vector(
168
- cls,
169
- min: tuple[float, float, float] | list[float] | LINKABLE = (0.0, 0.0, 0.0),
170
- max: tuple[float, float, float] | list[float] | LINKABLE = (1.0, 1.0, 1.0),
171
- id: int | LINKABLE | None = None,
172
- seed: int | LINKABLE = 1,
173
- ) -> NodeBuilder:
174
- buidler = cls(Min=min, Max=max, id=id, seed=seed, data_type="FLOAT_VECTOR")
175
- buidler._default_output_id = "Value"
176
- return buidler
177
-
178
-
179
- class SeparateXYZ(NodeBuilder):
180
- """Split a vector into its X, Y, and Z components"""
181
-
182
- name = "ShaderNodeSeparateXYZ"
183
- node: bpy.types.ShaderNodeSeparateXYZ # type: ignore
184
-
185
- def __init__(self, vector: TYPE_INPUT_VECTOR | None = None):
186
- super().__init__()
187
- self._establish_links(**{"Vector": vector})
188
-
189
- @property
190
- def i_vector(self) -> NodeSocket:
191
- """Input socket: Vector"""
192
- return self._input("Vector")
193
-
194
- @property
195
- def o_x(self) -> NodeSocket:
196
- """Output socket: X"""
197
- return self._output("X")
198
-
199
- @property
200
- def o_y(self) -> NodeSocket:
201
- """Output socket: Y"""
202
- return self._output("Y")
203
-
204
- @property
205
- def o_z(self) -> NodeSocket:
206
- """Output socket: Z"""
207
- return self._output("Z")
208
-
209
-
210
- class CombineXYZ(NodeBuilder):
211
- """Create a vector from X, Y, and Z components"""
212
-
213
- name = "ShaderNodeCombineXYZ"
214
- node: bpy.types.ShaderNodeCombineXYZ # type: ignore
215
-
216
- def __init__(
217
- self,
218
- x: float | LINKABLE = 0.0,
219
- y: float | LINKABLE = 0.0,
220
- z: float | LINKABLE = 0.0,
221
- ):
222
- super().__init__()
223
- self._establish_links(**{"X": x, "Y": y, "Z": z})
224
-
225
- @property
226
- def o_vector(self) -> NodeSocket:
227
- """Output socket: Vector"""
228
- return self._output("Vector")
229
-
230
- @property
231
- def i_x(self) -> NodeSocket:
232
- """Input socket: X"""
233
- return self._input("X")
234
-
235
- @property
236
- def i_y(self) -> NodeSocket:
237
- """Input socket: Y"""
238
- return self._input("Y")
239
-
240
- @property
241
- def i_z(self) -> NodeSocket:
242
- """Input socket: Z"""
243
- return self._input("Z")
244
-
245
-
246
- _MIX_VALUE_DATA_TYPES = Literal["FLOAT", "VECTOR", "COLOR", "ROTATION"]
247
-
248
-
249
- class Mix(NodeBuilder):
250
- """Mix values by a factor"""
251
-
252
- name = "ShaderNodeMix"
253
- node: bpy.types.ShaderNodeMix # type: ignore
254
-
255
- def __init__(
256
- self,
257
- data_type: _MIX_VALUE_DATA_TYPES = "FLOAT",
258
- **kwargs,
259
- ):
260
- super().__init__()
261
- self._default_input_id = f"A_{data_type.title()}"
262
- self._default_output_id = f"Result_{data_type.title()}"
263
- self.node.data_type = "RGBA" if data_type == "COLOR" else data_type
264
- key_args = {}
265
- key_args.update(kwargs)
266
- self._establish_links(**key_args)
267
-
268
- @property
269
- def data_type(self) -> str:
270
- return self.node.data_type
271
-
272
- @data_type.setter
273
- def data_type(self, value: _MIX_VALUE_DATA_TYPES):
274
- self.node.data_type = value # type: ignore
275
-
276
- @property
277
- def factor_mode(self) -> Literal["UNIFORM", "NON_UNIFORM"]:
278
- return self.node.factor_mode
279
-
280
- @factor_mode.setter
281
- def factor_mode(self, value: Literal["NON_UNIFORM", "UNIFORM"]):
282
- self.node.factor_mode = value
283
-
284
- @property
285
- def o_result(self) -> NodeSocket:
286
- """Output socket: Result"""
287
- return self._default_output_socket
288
-
289
- @property
290
- def i_factor(self) -> NodeSocket:
291
- """Input socket: Factor"""
292
- match self.data_type:
293
- case "FLOAT":
294
- name = "Factor_Float"
295
- case "VECTOR":
296
- name = (
297
- "Factor_Float" if self.factor_mode == "UNIFORM" else "Factor_Vector"
298
- )
299
- case "RGBA":
300
- name = "Factor_Color"
301
- case "ROTATION":
302
- name = "Factor_Rotation"
303
- case _:
304
- raise ValueError(f"Unsupported data type: {self.data_type}")
305
-
306
- idx = self._input_idx(name)
307
- return self.node.inputs[idx]
308
-
309
- @property
310
- def i_value_a(self) -> NodeSocket:
311
- """Input socket: Value A"""
312
- type_name = "Color" if self.data_type == "RGBA" else self.data_type
313
- name = f"A_{type_name}"
314
- idx = self._input_idx(name)
315
- return self.node.inputs[idx]
316
-
317
- @property
318
- def i_value_b(self) -> NodeSocket:
319
- """Input socket: Value B"""
320
- type_name = "Color" if self.data_type == "RGBA" else self.data_type
321
- name = f"B_{type_name}"
322
- idx = self._input_idx(name)
323
- return self.node.inputs[idx]
324
-
325
- @classmethod
326
- def float(
327
- cls,
328
- factor: float | LINKABLE = 0.5,
329
- a: float | LINKABLE = 0.0,
330
- b: float | LINKABLE = 0.0,
331
- clamp_factor: bool | LINKABLE = True,
332
- ) -> Mix:
333
- builder = cls(
334
- Factor_Float=factor,
335
- A_Float=a,
336
- B_Float=b,
337
- data_type="COLOR",
338
- )
339
- builder.node.clamp_factor = clamp_factor
340
- return builder
341
-
342
- @classmethod
343
- def vector(
344
- cls,
345
- factor: float | LINKABLE = 0.5,
346
- a: tuple[float, float, float] | list[float] | LINKABLE = (0.0, 0.0, 0.0),
347
- b: tuple[float, float, float] | list[float] | LINKABLE = (1.0, 1.0, 1.0),
348
- clamp_factor: bool = True,
349
- factor_mode: Literal["UNIFORM", "NON_UNIFORM"] = "UNIFORM",
350
- ) -> Mix:
351
- match factor_mode:
352
- case "UNIFORM":
353
- builder = cls(
354
- Factor_Float=factor,
355
- A_Vector=a,
356
- B_Vector=b,
357
- data_type="VECTOR",
358
- )
359
- case "NON_UNIFORM":
360
- builder = cls(
361
- Factor_Vector=factor,
362
- A_Vector=a,
363
- B_Vector=b,
364
- data_type="VECTOR",
365
- )
366
-
367
- builder.node.clamp_factor = clamp_factor
368
- return builder
369
-
370
- @classmethod
371
- def color(
372
- cls,
373
- factor: float | LINKABLE = 0.5,
374
- a: tuple[float, float, float] | list[float] | LINKABLE = (0.0, 0.0, 0.0),
375
- b: tuple[float, float, float] | list[float] | LINKABLE = (1.0, 1.0, 1.0),
376
- blend_type: str = "add",
377
- clamp_factor: bool = True,
378
- clamp_result: bool = True,
379
- ) -> Mix:
380
- builder = cls(
381
- Factor_Float=factor,
382
- A_Color=a,
383
- B_Color=b,
384
- data_type="COLOR",
385
- )
386
- builder.node.blend_type = blend_type.capitalize()
387
- builder.node.clamp_factor = clamp_factor
388
- builder.node.clamp_result = clamp_result
389
- return builder
390
-
391
- @classmethod
392
- def rotation(
393
- cls,
394
- a: tuple[float, float, float, float] | list[float] | LINKABLE | None = None,
395
- b: tuple[float, float, float, float] | list[float] | LINKABLE | None = None,
396
- factor: float | LINKABLE = 0.5,
397
- clamp_factor: bool = True,
398
- ) -> Mix:
399
- builder = cls(
400
- Factor_Float=factor,
401
- A_Rotation=a,
402
- B_Rotation=b,
403
- data_type="ROTATION",
404
- )
405
- builder.node.clamp_factor = clamp_factor
406
- return builder
407
-
408
-
409
- _AttributeDataTypes = Literal[
410
- "FLOAT", "INT", "BOOLEAN", "VECTOR", "RGBA", "ROTATION", "MATRIX"
411
- ]
412
-
413
-
414
- class CaptureAttribute(NodeBuilder):
415
- """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"""
416
-
417
- name = "GeometryNodeCaptureAttribute"
418
- node: bpy.types.GeometryNodeCaptureAttribute
419
-
420
- def __init__(
421
- self,
422
- geometry: LINKABLE = None,
423
- domain: _AttributeDomains = "POINT",
424
- **kwargs,
425
- ):
426
- super().__init__()
427
- key_args = {"Geometry": geometry}
428
- key_args.update(kwargs)
429
- self.domain = domain
430
- self._establish_links(**key_args)
431
-
432
- def capture(
433
- self,
434
- value: LINKABLE,
435
- name: str | None = None,
436
- data_type: _AttributeDataTypes | None = None,
437
- ):
438
- """Capture the value to store in the attribute"""
439
- source = source_socket(value)
440
- if name is None:
441
- name = source.name
442
- if data_type is None:
443
- data_type = source.type # type: ignore
444
-
445
- item = self._add_item(name, data_type) # type: ignore
446
- self._establish_links(**{item.name: value})
447
- return SocketLinker(self.node.outputs[item.name])
448
-
449
- def _add_item(
450
- self, name: str, data_type: _AttributeDataTypes = "FLOAT"
451
- ) -> bpy.types.NodeGeometryCaptureAttributeItem:
452
- """Add a new output socket to capture additional attributes"""
453
- return self._items.new(data_type, name)
454
-
455
- @property
456
- def _items(self) -> bpy.types.NodeGeometryCaptureAttributeItems:
457
- return self.node.capture_items
458
-
459
- @property
460
- def i_geometry(self) -> NodeSocket:
461
- """Input socket: Geometry"""
462
- return self._input("Geometry")
463
-
464
- @property
465
- def o_geometry(self) -> NodeSocket:
466
- """Output socket: Geometry"""
467
- return self._output("Geometry")
468
-
469
- @property
470
- def domain(
471
- self,
472
- ) -> _AttributeDomains:
473
- return self.node.domain
474
-
475
- @domain.setter
476
- def domain(
477
- self,
478
- value: _AttributeDomains,
479
- ):
480
- self.node.domain = value
481
-
482
-
483
- class JoinGeometry(NodeBuilder):
484
- """Merge separately generated geometries into a single one"""
485
-
486
- name = "GeometryNodeJoinGeometry"
487
- node: bpy.types.GeometryNodeJoinGeometry
488
-
489
- def __init__(self, geometry: NodeBuilder | Iterable[NodeBuilder] | None = None):
490
- super().__init__()
491
- if geometry is None:
492
- return
493
- elif isinstance(geometry, NodeBuilder):
494
- geometry = [geometry]
495
- for source in reversed(geometry):
496
- self.link_from(source, self)
497
-
498
- @property
499
- def i_geometry(self) -> NodeSocket:
500
- """Input socket: Geometry"""
501
- return self._input("Geometry")
502
-
503
- @property
504
- def o_geometry(self) -> NodeSocket:
505
- """Output socket: Geometry"""
506
- return self._output("Geometry")
507
-
508
-
509
- class Math(NodeBuilder):
510
- """Perform math operations"""
511
-
512
- name = "ShaderNodeMath"
513
- node: bpy.types.ShaderNodeMath # type: ignore
514
-
515
- def __init__(
516
- self,
517
- operation: types.NodeMathItems = "ADD",
518
- use_clamp: bool = False,
519
- **kwargs,
520
- ):
521
- super().__init__()
522
- self.operation = operation
523
- self.use_clamp = use_clamp
524
- self._establish_links(**kwargs)
525
-
526
- @property
527
- def operation(self) -> types.NodeMathItems:
528
- return self.node.operation
529
-
530
- @operation.setter
531
- def operation(self, value: types.NodeMathItems):
532
- self.node.operation = value
533
-
534
- @property
535
- def use_clamp(self) -> bool:
536
- return self.node.use_clamp
537
-
538
- @use_clamp.setter
539
- def use_clamp(self, value: bool):
540
- self.node.use_clamp = value
541
-
542
- @property
543
- def o_value(self) -> NodeSocketFloat:
544
- return self._output("Value") # type: ignore
545
-
546
- def _input(self, identifier: str) -> NodeSocketFloat:
547
- return self._input(identifier)
548
-
549
- @property
550
- def i_value(self) -> NodeSocketFloat:
551
- return self._input("Value")
552
-
553
- @property
554
- def i_value_001(self) -> NodeSocketFloat:
555
- return self._input("Value_001")
556
-
557
- @property
558
- def i_value_002(self) -> NodeSocketFloat:
559
- return self._input("Value_002")
560
-
561
- @classmethod
562
- def add(
563
- cls,
564
- a: float | LINKABLE = 0.5,
565
- b: float | LINKABLE = 0.5,
566
- ) -> "Math":
567
- """Create Math with operation of `a + b`."""
568
- return cls(operation="ADD", Value=a, Value_001=b)
569
-
570
- @classmethod
571
- def subtract(
572
- cls,
573
- a: float | LINKABLE = 0.5,
574
- b: float | LINKABLE = 0.5,
575
- ) -> "Math":
576
- """Create Math with operation of `a - b`."""
577
- return cls(operation="SUBTRACT", Value=a, Value_001=b)
578
-
579
- @classmethod
580
- def multiply(
581
- cls,
582
- a: float | LINKABLE = 0.5,
583
- b: float | LINKABLE = 0.5,
584
- ) -> "Math":
585
- """Create Math with operation of `a * b`."""
586
- return cls(operation="MULTIPLY", Value=a, Value_001=b)
587
-
588
- @classmethod
589
- def divide(
590
- cls,
591
- a: float | LINKABLE = 0.5,
592
- b: float | LINKABLE = 0.5,
593
- ) -> "Math":
594
- """Create Math with operation of `a / b`."""
595
- return cls(operation="DIVIDE", Value=a, Value_001=b)
596
-
597
- @classmethod
598
- def multiply_add(
599
- cls,
600
- a: float | LINKABLE = 0.5,
601
- b: float | LINKABLE = 0.5,
602
- c: float | LINKABLE = 0.5,
603
- ) -> "Math":
604
- """Create Math with operation `a * b + c`."""
605
- return cls(operation="MULTIPLY_ADD", Value=a, Value_001=b, value_002=c)
606
-
607
- @classmethod
608
- def power(
609
- cls,
610
- base: float | LINKABLE = 0.5,
611
- exponent: float | LINKABLE = 0.5,
612
- ) -> "Math":
613
- """Create Math with operation `base ** exponent`."""
614
- return cls(operation="POWER", Value=base, Value_001=exponent)
615
-
616
- @classmethod
617
- def logarithm(
618
- cls,
619
- value: float | LINKABLE = 0.5,
620
- base: float | LINKABLE = 0.5,
621
- ) -> "Math":
622
- """Create Math with operation `log(value, base)`."""
623
- return cls(operation="LOGARITHM", Value=value, Value_001=base)
624
-
625
- @classmethod
626
- def sqrt(
627
- cls,
628
- value: float | LINKABLE = 0.5,
629
- ) -> "Math":
630
- """Create Math with operation `sqrt(value)`."""
631
- return cls(operation="SQRT", Value=value)
632
-
633
- @classmethod
634
- def inverse_sqrt(
635
- cls,
636
- value: float | LINKABLE = 0.5,
637
- ) -> "Math":
638
- """Create Math with operation `inverse_sqrt(value)`."""
639
- return cls(operation="INVERSE_SQRT", Value=value)
640
-
641
- @classmethod
642
- def absolute(
643
- cls,
644
- value: float | LINKABLE = 0.5,
645
- ) -> "Math":
646
- """Create Math with operation `abs(value)`."""
647
- return cls(operation="ABSOLUTE", Value=value)
648
-
649
- @classmethod
650
- def exponent(
651
- cls,
652
- value: float | LINKABLE = 0.5,
653
- ) -> "Math":
654
- """Create Math with operation `exp(value)`."""
655
- return cls(operation="EXPONENT", Value=value)
656
-
657
- @classmethod
658
- def minimum(
659
- cls,
660
- a: float | LINKABLE = 0.5,
661
- b: float | LINKABLE = 0.5,
662
- ) -> "Math":
663
- """Create Math with operation `min(a, b)`."""
664
- return cls(operation="MINIMUM", Value=a, Value_001=b)
665
-
666
- @classmethod
667
- def maximum(
668
- cls,
669
- a: float | LINKABLE = 0.5,
670
- b: float | LINKABLE = 0.5,
671
- ) -> "Math":
672
- """Create Math with operation `max(a, b)`."""
673
- return cls(operation="MAXIMUM", Value=a, Value_001=b)
674
-
675
- @classmethod
676
- def less_than(
677
- cls,
678
- value: float | LINKABLE = 0.5,
679
- threshold: float | LINKABLE = 0.5,
680
- ) -> "Math":
681
- """Create Math with operation `value < threshold` returning 1 or 0."""
682
- return cls(operation="LESS_THAN", Value=value, Value_001=threshold)
683
-
684
- @classmethod
685
- def greater_than(
686
- cls,
687
- value: float | LINKABLE = 0.5,
688
- threshold: float | LINKABLE = 0.5,
689
- ) -> "Math":
690
- """Create Math with operation `value > threshold` returning 1 or 0."""
691
- return cls(operation="GREATER_THAN", Value=value, Value_001=threshold)
692
-
693
- @classmethod
694
- def sign(
695
- cls,
696
- value: float | LINKABLE = 0.5,
697
- ) -> "Math":
698
- """Create Math with operation `sign(value)` returning -1, 0, or 1."""
699
- return cls(operation="SIGN", Value=value)
700
-
701
- @classmethod
702
- def compare(
703
- cls,
704
- a: float | LINKABLE = 0.5,
705
- b: float | LINKABLE = 0.5,
706
- epsilon: float | LINKABLE = 0.5,
707
- ) -> "Math":
708
- """Create Math with operation `compare(a, b, epsilon)` returning -1, 0, or 1."""
709
- return cls(operation="COMPARE", Value=a, Value_001=b, value_002=epsilon)
710
-
711
- @classmethod
712
- def smooth_min(
713
- cls,
714
- a: float | LINKABLE = 0.5,
715
- b: float | LINKABLE = 0.5,
716
- distance: float | LINKABLE = 0.5,
717
- ) -> "Math":
718
- """Create Math with operation `smooth_min(a, b, distance)`."""
719
- return cls(operation="SMOOTH_MIN", Value=a, Value_001=b, value_002=distance)
720
-
721
- @classmethod
722
- def smooth_max_(
723
- cls,
724
- a: float | LINKABLE = 0.5,
725
- b: float | LINKABLE = 0.5,
726
- distance: float | LINKABLE = 0.5,
727
- ) -> "Math":
728
- """Create Math with operation `smooth_max(a, b, distance)`."""
729
- return cls(operation="SMOOTH_MAX", Value=a, Value_001=b, value_002=distance)
730
-
731
- @classmethod
732
- def round(
733
- cls,
734
- value: float | LINKABLE = 0.5,
735
- ) -> "Math":
736
- """Round A to the nearest integer. Round up if 0.5 or greater."""
737
- return cls(operation="ROUND", Value=value)
738
-
739
- @classmethod
740
- def floor(
741
- cls,
742
- value: float | LINKABLE = 0.5,
743
- ) -> "Math":
744
- """The largest integer smaller than or equal to `value`"""
745
- return cls(operation="FLOOR", Value=value)
746
-
747
- @classmethod
748
- def ceil(
749
- cls,
750
- value: float | LINKABLE = 0.5,
751
- ) -> "Math":
752
- """The smallest integer greater than or equal to `value`"""
753
- return cls(operation="CEIL", Value=value)
754
-
755
- @classmethod
756
- def truncate(
757
- cls,
758
- value: float | LINKABLE = 0.5,
759
- ) -> "Math":
760
- """The integer part of `value` removing the fractional part"""
761
- return cls(operation="TRUNC", Value=value)
762
-
763
- @classmethod
764
- def fraction(
765
- cls,
766
- value: float | LINKABLE = 0.5,
767
- ) -> "Math":
768
- """The fractional part of `value`"""
769
- return cls(operation="FRACT", Value=value)
770
-
771
- @classmethod
772
- def truncated_modulo(
773
- cls,
774
- a: float | LINKABLE = 0.5,
775
- b: float | LINKABLE = 0.5,
776
- ) -> "Math":
777
- """The remained of truncated division using fmod(a, b)"""
778
- return cls(operation="MODULO", Value=a, Value_001=b)
779
-
780
- @classmethod
781
- def floored_modulo(
782
- cls,
783
- a: float | LINKABLE = 0.5,
784
- b: float | LINKABLE = 0.5,
785
- ) -> "Math":
786
- """The remained of floored division"""
787
- return cls(operation="FLOORED_MODULO", Value=a, Value_001=b)
788
-
789
- @classmethod
790
- def wrap(
791
- cls,
792
- value: float | LINKABLE = 0.5,
793
- max: float | LINKABLE = 0.5,
794
- min: float | LINKABLE = 0.5,
795
- ) -> "Math":
796
- """Wrap value to range, wrap(value, max, min)"""
797
- return cls(operation="WRAP", Value=value, Value_001=max, value_002=min)
798
-
799
- @classmethod
800
- def snap(
801
- cls,
802
- value: float | LINKABLE = 0.5,
803
- increment: float | LINKABLE = 0.5,
804
- ) -> "Math":
805
- """Snap to increment of `snap(value, increment)`"""
806
- return cls(operation="SNAP", Value=value, Value_001=increment)
807
-
808
- @classmethod
809
- def ping_pong(
810
- cls,
811
- value: float | LINKABLE = 0.5,
812
- scale: float | LINKABLE = 0.5,
813
- ) -> "Math":
814
- """Wraps a value and reverses every other cycle"""
815
- return cls(operation="PINGPONG", Value=value, Value_001=scale)
816
-
817
- @classmethod
818
- def sine(
819
- cls,
820
- value: float | LINKABLE = 0.5,
821
- ) -> "Math":
822
- """Create Math with operation 'sin(value)'."""
823
- return cls(operation="SINE", Value=value)
824
-
825
- @classmethod
826
- def cosine(
827
- cls,
828
- value: float | LINKABLE = 0.5,
829
- ) -> "Math":
830
- """Create Math with operation 'cos(value)'."""
831
- return cls(operation="COSINE", Value=value)
832
-
833
- @classmethod
834
- def tangent(
835
- cls,
836
- value: float | LINKABLE = 0.5,
837
- ) -> "Math":
838
- """Create Math with operation 'tan(value)'."""
839
- return cls(operation="TANGENT", Value=value)
840
-
841
- @classmethod
842
- def arcsine(
843
- cls,
844
- value: float | LINKABLE = 0.5,
845
- ) -> "Math":
846
- """Create Math with operation `arcsin(value)'."""
847
- return cls(operation="ARCSINE", Value=value)
848
-
849
- @classmethod
850
- def arccosine(
851
- cls,
852
- value: float | LINKABLE = 0.5,
853
- ) -> "Math":
854
- """Create Math with operation 'arccos(value)'."""
855
- return cls(operation="ARCCOSINE", Value=value)
856
-
857
- @classmethod
858
- def arctangent(
859
- cls,
860
- value: float | LINKABLE = 0.5,
861
- ) -> "Math":
862
- """Create Math with operation 'arctan(value)'."""
863
- return cls(operation="ARCTANGENT", Value=value)
864
-
865
- @classmethod
866
- def arctan2(
867
- cls,
868
- a: float | LINKABLE = 0.5,
869
- b: float | LINKABLE = 0.5,
870
- ) -> "Math":
871
- """Create Math with operation 'arctan(a / b)'."""
872
- return cls(operation="ARCTAN2", Value=a, Value_001=b)
873
-
874
- @classmethod
875
- def sinh(
876
- cls,
877
- value: float | LINKABLE = 0.5,
878
- ) -> "Math":
879
- """Create Math with operation `sinh(value)`."""
880
- return cls(operation="SINH", Value=value)
881
-
882
- @classmethod
883
- def cosh(
884
- cls,
885
- value: float | LINKABLE = 0.5,
886
- ) -> "Math":
887
- """Create Math with operation `cosh(value)`."""
888
- return cls(operation="COSH", Value=value)
889
-
890
- @classmethod
891
- def tanh(
892
- cls,
893
- value: float | LINKABLE = 0.5,
894
- ) -> "Math":
895
- """Create Math with operation `tanh(value)`."""
896
- return cls(operation="TANH", Value=value)
897
-
898
- @classmethod
899
- def radians(
900
- cls,
901
- degrees: float | LINKABLE = 0.5,
902
- ) -> "Math":
903
- """Create Math with operation `radians(degrees)`."""
904
- return cls(operation="RADIANS", Value=degrees)
905
-
906
- @classmethod
907
- def degrees(
908
- cls,
909
- radians: float | LINKABLE = 0.5,
910
- ) -> "Math":
911
- """Create Math with operation 'To Degrees'."""
912
- return cls(operation="DEGREES", Value=radians)
913
-
914
-
915
- class BooleanMath(NodeBuilder):
916
- """Boolean Math node"""
917
-
918
- name = "FunctionNodeBooleanMath"
919
- node: bpy.types.FunctionNodeBooleanMath
920
-
921
- def __init__(self, operation: types.NodeBooleanMathItems = "AND", **kwargs):
922
- super().__init__()
923
- self.operator = operation
924
- self._establish_links(**kwargs)
925
-
926
- @property
927
- def operation(self) -> types.NodeBooleanMathItems:
928
- return self.node.operation
929
-
930
- @operation.setter
931
- def operation(self, value: types.NodeBooleanMathItems):
932
- self.node.operation = value
933
-
934
- @property
935
- def i_boolean(self) -> bpy.types.NodeSocketBool:
936
- return self._input("Boolean") # type: ignore
937
-
938
- @property
939
- def i_boolean_001(self) -> bpy.types.NodeSocketBool:
940
- return self._input("Boolean_001") # type: ignore
941
-
942
- @property
943
- def o_boolean(self) -> bpy.types.NodeSocketBool:
944
- return self._output("Boolean") # type: ignore
945
-
946
- @classmethod
947
- def l_and(
948
- cls,
949
- boolean: TYPE_INPUT_BOOLEAN = False,
950
- boolean_001: TYPE_INPUT_BOOLEAN = False,
951
- ) -> "BooleanMath":
952
- """Create Boolean Math with operation 'AND'."""
953
- return cls(operation="AND", Boolean=boolean, Boolean_001=boolean_001)
954
-
955
- @classmethod
956
- def l_or(
957
- cls,
958
- boolean: TYPE_INPUT_BOOLEAN = False,
959
- boolean_001: TYPE_INPUT_BOOLEAN = False,
960
- ) -> "BooleanMath":
961
- """Create Boolean Math with operation 'OR'."""
962
- return cls(operation="OR", Boolean=boolean, Boolean_001=boolean_001)
963
-
964
- @classmethod
965
- def l_not(cls, boolean: TYPE_INPUT_BOOLEAN = False) -> "BooleanMath":
966
- """Create Boolean Math with operation 'NOT'."""
967
- return cls(operation="NOT", Boolean=boolean)
968
-
969
- @classmethod
970
- def l_not_and(
971
- cls,
972
- boolean: TYPE_INPUT_BOOLEAN = False,
973
- boolean_001: TYPE_INPUT_BOOLEAN = False,
974
- ) -> "BooleanMath":
975
- """Create Boolean Math with operation 'NAND'."""
976
- return cls(operation="NAND", Boolean=boolean, Boolean_001=boolean_001)
977
-
978
- @classmethod
979
- def l_nor(
980
- cls,
981
- boolean: TYPE_INPUT_BOOLEAN = False,
982
- boolean_001: TYPE_INPUT_BOOLEAN = False,
983
- ) -> "BooleanMath":
984
- """Create Boolean Math with operation 'NOR'."""
985
- return cls(operation="NOR", Boolean=boolean, Boolean_001=boolean_001)
986
-
987
- @classmethod
988
- def l_equal(
989
- cls,
990
- boolean: TYPE_INPUT_BOOLEAN = False,
991
- boolean_001: TYPE_INPUT_BOOLEAN = False,
992
- ) -> "BooleanMath":
993
- """Create Boolean Math with operation 'XNOR'."""
994
- return cls(operation="XNOR", Boolean=boolean, Boolean_001=boolean_001)
995
-
996
- @classmethod
997
- def l_not_equal(
998
- cls,
999
- boolean: TYPE_INPUT_BOOLEAN = False,
1000
- boolean_001: TYPE_INPUT_BOOLEAN = False,
1001
- ) -> "BooleanMath":
1002
- """Create Boolean Math with operation 'XOR'."""
1003
- return cls(operation="XOR", Boolean=boolean, Boolean_001=boolean_001)
1004
-
1005
- @classmethod
1006
- def l_imply(
1007
- cls,
1008
- boolean: TYPE_INPUT_BOOLEAN = False,
1009
- boolean_001: TYPE_INPUT_BOOLEAN = False,
1010
- ) -> "BooleanMath":
1011
- """Create Boolean Math with operation 'IMPLY'."""
1012
- return cls(operation="IMPLY", Boolean=boolean, Boolean_001=boolean_001)
1013
-
1014
- @classmethod
1015
- def l_subtract(
1016
- cls,
1017
- boolean: TYPE_INPUT_BOOLEAN = False,
1018
- boolean_001: TYPE_INPUT_BOOLEAN = False,
1019
- ) -> "BooleanMath":
1020
- """Create Boolean Math with operation 'NIMPLY'."""
1021
- return cls(operation="NIMPLY", Boolean=boolean, Boolean_001=boolean_001)
1022
-
1023
-
1024
- _VectorMathOperations = Literal[
1025
- "ADD",
1026
- "SUBTRACT",
1027
- "MULTIPLY",
1028
- "DIVIDE",
1029
- "MULTIPLY_ADD",
1030
- "CROSS_PRODUCT",
1031
- "PROJECT",
1032
- "REFLECT",
1033
- "REFRACT",
1034
- "FACEFORWARD",
1035
- "DOT_PRODUCT",
1036
- "DISTANCE",
1037
- "LENGTH",
1038
- "SCALE",
1039
- "NORMALIZE",
1040
- "ABSOLUTE",
1041
- "POWER",
1042
- "SIGN",
1043
- "MINIMUM",
1044
- "MAXIMUM",
1045
- "FLOOR",
1046
- "CEIL",
1047
- "FRACTION",
1048
- "MODULO",
1049
- "WRAP",
1050
- "SNAP",
1051
- "SINE",
1052
- "COSINE",
1053
- "TANGENT",
1054
- ]
1055
-
1056
-
1057
- class VectorMath(NodeBuilder):
1058
- """Perform vector math operation"""
1059
-
1060
- name = "ShaderNodeVectorMath"
1061
- node: bpy.types.ShaderNodeVectorMath
1062
-
1063
- def __init__(
1064
- self,
1065
- operation: _VectorMathOperations = "ADD",
1066
- **kwargs,
1067
- ):
1068
- super().__init__()
1069
- self.operation = operation
1070
- self._establish_links(**kwargs)
1071
-
1072
- @property
1073
- def i_vector(self) -> bpy.types.NodeSocketVector:
1074
- """Input socket: Vector"""
1075
- return self._input("Vector")
1076
-
1077
- @property
1078
- def i_vector_001(self) -> bpy.types.NodeSocketVector:
1079
- """Input socket: Vector"""
1080
- return self._input("Vector_001")
1081
-
1082
- @property
1083
- def o_vector(self) -> bpy.types.NodeSocketVector:
1084
- """Output socket: Vector"""
1085
- if self.operation in {"DOT_PRODUCT", "DISTANCE", "LENGTH"}:
1086
- raise RuntimeError(
1087
- f"Output 'Vector' is not available for operation '{self.operation}'"
1088
- )
1089
- return self._output("Vector")
1090
-
1091
- def o_value(self) -> bpy.types.NodeSocketFloat:
1092
- """Output socket: Value"""
1093
- if self.operation not in {"DOT_PRODUCT", "DISTANCE", "LENGTH"}:
1094
- raise RuntimeError(
1095
- f"Output 'Value' is not available for operation '{self.operation}'"
1096
- )
1097
- return self._output("Value")
1098
-
1099
- @property
1100
- def _default_output_socket(self) -> NodeSocketFloat | NodeSocketVector:
1101
- match self.operation:
1102
- case "DOT_PRODUCT" | "DISTANCE" | "LENGTH":
1103
- return self.o_value
1104
- case _:
1105
- return self.o_vector
1106
-
1107
- @property
1108
- def operation(
1109
- self,
1110
- ) -> _VectorMathOperations:
1111
- return self.node.operation
1112
-
1113
- @operation.setter
1114
- def operation(
1115
- self,
1116
- value: _VectorMathOperations,
1117
- ):
1118
- self.node.operation = value
1119
-
1120
- @classmethod
1121
- def add(
1122
- cls,
1123
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1124
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1125
- ) -> "VectorMath":
1126
- """Create Vector Math with operation `a + b`."""
1127
- return cls(operation="ADD", Vector=a, Vector_001=b)
1128
-
1129
- @classmethod
1130
- def subtract(
1131
- cls,
1132
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1133
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1134
- ) -> "VectorMath":
1135
- """Create Vector Math with operation `a - b`."""
1136
- return cls(operation="SUBTRACT", Vector=a, Vector_001=b)
1137
-
1138
- @classmethod
1139
- def multiply(
1140
- cls,
1141
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1142
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1143
- ) -> "VectorMath":
1144
- """Create Vector Math with operation `a * b` element-wise."""
1145
- return cls(operation="MULTIPLY", Vector=a, Vector_001=b)
1146
-
1147
- @classmethod
1148
- def divide(
1149
- cls,
1150
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1151
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1152
- ) -> "VectorMath":
1153
- """Create Vector Math with operation 'Divide'."""
1154
- return cls(operation="DIVIDE", Vector=a, Vector_001=b)
1155
-
1156
- @classmethod
1157
- def multiply_add(
1158
- cls,
1159
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1160
- multiplier: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1161
- addend: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1162
- ) -> "VectorMath":
1163
- """Create Vector Math with operation 'Multiply Add'."""
1164
- return cls(
1165
- operation="MULTIPLY_ADD",
1166
- Vector=vector,
1167
- Vector_001=multiplier,
1168
- Vector_002=addend,
1169
- )
1170
-
1171
- @classmethod
1172
- def cross_product(
1173
- cls,
1174
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1175
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1176
- ) -> "VectorMath":
1177
- """Create Vector Math with operation 'Cross Product'."""
1178
- return cls(operation="CROSS_PRODUCT", Vector=a, Vector_001=b)
1179
-
1180
- @classmethod
1181
- def project(
1182
- cls,
1183
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1184
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1185
- ) -> "VectorMath":
1186
- """Project A onto B."""
1187
- return cls(operation="PROJECT", Vector=a, Vector_001=b)
1188
-
1189
- @classmethod
1190
- def reflect(
1191
- cls,
1192
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1193
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1194
- ) -> "VectorMath":
1195
- """Reflect A around the normal B. B does not need to be normalized."""
1196
- return cls(operation="REFLECT", Vector=a, Vector_001=b)
1197
-
1198
- @classmethod
1199
- def refract(
1200
- cls,
1201
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1202
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1203
- ior: LINKABLE | float = 1.0,
1204
- ) -> "VectorMath":
1205
- """For a given incident vector and surface normal (b) with an index of refraction (ior), return the refraction vector"""
1206
- return cls(operation="REFRACT", Vector=a, Vector_001=b, Scale=ior)
1207
-
1208
- @classmethod
1209
- def face_forward(
1210
- cls,
1211
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1212
- incidence: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1213
- reference: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1214
- ) -> "VectorMath":
1215
- """Orients a vector to face away from a surface (incidence) defined by it's normal (reference)"""
1216
- return cls(
1217
- operation="FACEFORWARD",
1218
- Vector=vector,
1219
- Vector_001=incidence,
1220
- Vector_002=reference,
1221
- )
1222
-
1223
- @classmethod
1224
- def dot_product(
1225
- cls,
1226
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1227
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1228
- ) -> "VectorMath":
1229
- """Create Vector Math with operation 'Dot Product'."""
1230
- return cls(operation="DOT_PRODUCT", Vector=a, Vector_001=b)
1231
-
1232
- @classmethod
1233
- def distance(
1234
- cls,
1235
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1236
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1237
- ) -> "VectorMath":
1238
- """Create Vector Math with operation 'Distance'."""
1239
- return cls(operation="DISTANCE", Vector=a, Vector_001=b)
1240
-
1241
- @classmethod
1242
- def length(
1243
- cls,
1244
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1245
- ) -> "VectorMath":
1246
- """Create Vector Math with operation 'Length'."""
1247
- return cls(operation="LENGTH", Vector=vector)
1248
-
1249
- @classmethod
1250
- def scale(
1251
- cls,
1252
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1253
- scale: LINKABLE | float = 1.0,
1254
- ) -> "VectorMath":
1255
- """Create Vector Math with operation 'Scale'."""
1256
- return cls(operation="SCALE", Vector=vector, Scale=scale)
1257
-
1258
- @classmethod
1259
- def normalize(
1260
- cls,
1261
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1262
- ) -> "VectorMath":
1263
- """Create Vector Math with operation 'Normalize'."""
1264
- return cls(operation="NORMALIZE", Vector=vector)
1265
-
1266
- @classmethod
1267
- def absolute(
1268
- cls,
1269
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1270
- ) -> "VectorMath":
1271
- """Create Vector Math with operation 'Absolute'."""
1272
- return cls(operation="ABSOLUTE", Vector=vector)
1273
-
1274
- @classmethod
1275
- def power(
1276
- cls,
1277
- base: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1278
- exponent: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1279
- ) -> "VectorMath":
1280
- """Create Vector Math with operation 'Power'."""
1281
- return cls(operation="POWER", Vector=base, Vector_001=exponent)
1282
-
1283
- @classmethod
1284
- def sign(
1285
- cls,
1286
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1287
- ) -> "VectorMath":
1288
- """Create Vector Math with operation 'Sign'."""
1289
- return cls(operation="SIGN", Vector=vector)
1290
-
1291
- @classmethod
1292
- def minimum(
1293
- cls,
1294
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1295
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1296
- ) -> "VectorMath":
1297
- """Create Vector Math with operation 'Minimum'."""
1298
- return cls(operation="MINIMUM", Vector=a, Vector_001=b)
1299
-
1300
- @classmethod
1301
- def maximum(
1302
- cls,
1303
- a: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1304
- b: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1305
- ) -> "VectorMath":
1306
- """Create Vector Math with operation 'Maximum'."""
1307
- return cls(operation="MAXIMUM", Vector=a, Vector_001=b)
1308
-
1309
- @classmethod
1310
- def floor(
1311
- cls,
1312
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1313
- ) -> "VectorMath":
1314
- """Create Vector Math with operation 'Floor'."""
1315
- return cls(operation="FLOOR", Vector=vector)
1316
-
1317
- @classmethod
1318
- def ceil(
1319
- cls,
1320
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1321
- ) -> "VectorMath":
1322
- """Create Vector Math with operation 'Ceil'."""
1323
- return cls(operation="CEIL", Vector=vector)
1324
-
1325
- @classmethod
1326
- def fraction(
1327
- cls,
1328
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1329
- ) -> "VectorMath":
1330
- """Create Vector Math with operation 'Fraction'."""
1331
- return cls(operation="FRACTION", Vector=vector)
1332
-
1333
- @classmethod
1334
- def modulo(
1335
- cls,
1336
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1337
- ) -> "VectorMath":
1338
- """Create Vector Math with operation 'Modulo'."""
1339
- return cls(operation="MODULO", Vector=vector)
1340
-
1341
- @classmethod
1342
- def wrap(
1343
- cls,
1344
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1345
- min: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1346
- max: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1347
- ) -> "VectorMath":
1348
- """Create Vector Math with operation 'Wrap'."""
1349
- return cls(operation="WRAP", Vector=vector, Vector_001=min, Vector_002=max)
1350
-
1351
- @classmethod
1352
- def snap(
1353
- cls,
1354
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1355
- increment: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1356
- ) -> "VectorMath":
1357
- """Create Vector Math with operation 'Snap'."""
1358
- return cls(operation="SNAP", Vector=vector, Vector_001=increment)
1359
-
1360
- @classmethod
1361
- def sine(
1362
- cls,
1363
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1364
- ) -> "VectorMath":
1365
- """Create Vector Math with operation 'Sine'."""
1366
- return cls(operation="SINE", Vector=vector)
1367
-
1368
- @classmethod
1369
- def cosine(
1370
- cls,
1371
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1372
- ) -> "VectorMath":
1373
- """Create Vector Math with operation 'Cosine'."""
1374
- return cls(operation="COSINE", Vector=vector)
1375
-
1376
- @classmethod
1377
- def tangent(
1378
- cls,
1379
- vector: TYPE_INPUT_VECTOR = [0.0, 0.0, 0.0],
1380
- ) -> "VectorMath":
1381
- """Create Vector Math with operation 'Tangent'."""
1382
- return cls(operation="TANGENT", Vector=vector)