nodebpy 520.14.0__tar.gz → 520.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nodebpy-520.14.0 → nodebpy-520.16.0}/PKG-INFO +1 -1
- {nodebpy-520.14.0 → nodebpy-520.16.0}/pyproject.toml +1 -1
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/__init__.py +2 -1
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/items.py +63 -2
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/tree.py +42 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/export/codegen.py +15 -1
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/manual.py +8 -8
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/manual.py +141 -48
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/zone.py +16 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/manual.py +10 -10
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/types.py +1 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/README.md +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/assets/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/assets/__main__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/assets/_codegen.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/_registry.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/_utils.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/accessor.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/arrange.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/asset.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/mixins.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/node.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/builder/socket.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/export/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/export/diagram.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/export/web_render.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/config.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/lib/nodearrange/utils.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/_mixins.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/assets.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/color.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/converter.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/distort.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/filter.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/group.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/input.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/interface.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/matte.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/output.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/compositor/vector.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/assets.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/attribute.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/color.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/converter.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/geometry.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/grid.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/group.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/groups.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/input.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/interface.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/output.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/texture.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/utilities.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/geometry/vector.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/__init__.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/assets.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/color.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/converter.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/grid.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/group.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/input.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/output.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/script.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/shader.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/texture.py +0 -0
- {nodebpy-520.14.0 → nodebpy-520.16.0}/src/nodebpy/nodes/shader/vector.py +0 -0
|
@@ -9,7 +9,7 @@ from .asset import (
|
|
|
9
9
|
PackageLibrary,
|
|
10
10
|
asset_group_base,
|
|
11
11
|
)
|
|
12
|
-
from .items import Item, ItemsMixin
|
|
12
|
+
from .items import Item, ItemsMixin, MenuItem
|
|
13
13
|
from .mixins import LinkingMixin, OperatorMixin
|
|
14
14
|
from .node import (
|
|
15
15
|
BaseNode,
|
|
@@ -118,6 +118,7 @@ __all__ = [
|
|
|
118
118
|
"MaterialSocketList",
|
|
119
119
|
"MatrixSocket",
|
|
120
120
|
"MatrixSocketList",
|
|
121
|
+
"MenuItem",
|
|
121
122
|
"MenuSocket",
|
|
122
123
|
"MenuSocketList",
|
|
123
124
|
"NodeGroupBuilder",
|
|
@@ -10,7 +10,7 @@ from ..types import _is_default_value
|
|
|
10
10
|
from ._registry import _wrap_socket
|
|
11
11
|
from ._utils import _SocketLike
|
|
12
12
|
from .node import DynamicInputsMixin
|
|
13
|
-
from .socket import Socket
|
|
13
|
+
from .socket import BaseSocket, Socket
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
16
|
from ..types import (
|
|
@@ -21,6 +21,7 @@ if TYPE_CHECKING:
|
|
|
21
21
|
InputCollection,
|
|
22
22
|
InputColor,
|
|
23
23
|
InputFloat,
|
|
24
|
+
InputFont,
|
|
24
25
|
InputGeometry,
|
|
25
26
|
InputImage,
|
|
26
27
|
InputInteger,
|
|
@@ -30,6 +31,7 @@ if TYPE_CHECKING:
|
|
|
30
31
|
InputMenu,
|
|
31
32
|
InputObject,
|
|
32
33
|
InputRotation,
|
|
34
|
+
InputSound,
|
|
33
35
|
InputString,
|
|
34
36
|
InputVector,
|
|
35
37
|
_SocketShapeStructureType,
|
|
@@ -41,6 +43,7 @@ if TYPE_CHECKING:
|
|
|
41
43
|
CollectionSocket,
|
|
42
44
|
ColorSocket,
|
|
43
45
|
FloatSocket,
|
|
46
|
+
FontSocket,
|
|
44
47
|
GeometrySocket,
|
|
45
48
|
ImageSocket,
|
|
46
49
|
IntegerSocket,
|
|
@@ -49,6 +52,7 @@ if TYPE_CHECKING:
|
|
|
49
52
|
MenuSocket,
|
|
50
53
|
ObjectSocket,
|
|
51
54
|
RotationSocket,
|
|
55
|
+
SoundSocket,
|
|
52
56
|
StringSocket,
|
|
53
57
|
VectorSocket,
|
|
54
58
|
)
|
|
@@ -96,7 +100,7 @@ def _infer_value_type(value: Any) -> str | None:
|
|
|
96
100
|
return None
|
|
97
101
|
|
|
98
102
|
|
|
99
|
-
_SocketT = TypeVar("_SocketT", bound=
|
|
103
|
+
_SocketT = TypeVar("_SocketT", bound=BaseSocket, default=Socket)
|
|
100
104
|
|
|
101
105
|
|
|
102
106
|
class Item(Generic[_SocketT]):
|
|
@@ -152,6 +156,29 @@ class Item(Generic[_SocketT]):
|
|
|
152
156
|
)
|
|
153
157
|
|
|
154
158
|
|
|
159
|
+
class MenuItem(Item[_SocketT]):
|
|
160
|
+
"""Handle for one Menu Switch enum item.
|
|
161
|
+
|
|
162
|
+
``input`` is the item's input socket (typed to the switch's data
|
|
163
|
+
type), ``is_selected`` the item's boolean output socket, and
|
|
164
|
+
``description`` the tooltip Blender shows for the item in the menu.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def is_selected(self) -> BooleanSocket:
|
|
169
|
+
"""Boolean output socket — True when this item is selected."""
|
|
170
|
+
return cast("BooleanSocket", self.output)
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def description(self) -> str:
|
|
174
|
+
"""Tooltip shown for this item in the drop-down menu."""
|
|
175
|
+
return self._item.description
|
|
176
|
+
|
|
177
|
+
@description.setter
|
|
178
|
+
def description(self, value: str) -> None:
|
|
179
|
+
self._item.description = value
|
|
180
|
+
|
|
181
|
+
|
|
155
182
|
class ItemsMixin(DynamicInputsMixin):
|
|
156
183
|
"""Socket machinery for nodes whose sockets are driven by a bpy item
|
|
157
184
|
collection (``capture_items``, ``bake_items``, ``format_items``, ...).
|
|
@@ -511,6 +538,22 @@ class _SocketItemFactory(_TypedItemFactory):
|
|
|
511
538
|
) -> MaterialSocket:
|
|
512
539
|
return cast("MaterialSocket", self._declare(name, "MATERIAL", structure_type))
|
|
513
540
|
|
|
541
|
+
def font(
|
|
542
|
+
self,
|
|
543
|
+
name: str = "Font",
|
|
544
|
+
*,
|
|
545
|
+
structure_type: _SocketShapeStructureType = "AUTO",
|
|
546
|
+
) -> FontSocket:
|
|
547
|
+
return cast("FontSocket", self._declare(name, "FONT", structure_type))
|
|
548
|
+
|
|
549
|
+
def sound(
|
|
550
|
+
self,
|
|
551
|
+
name: str = "Sound",
|
|
552
|
+
*,
|
|
553
|
+
structure_type: _SocketShapeStructureType = "AUTO",
|
|
554
|
+
) -> SoundSocket:
|
|
555
|
+
return cast("SoundSocket", self._declare(name, "SOUND", structure_type))
|
|
556
|
+
|
|
514
557
|
def bundle(
|
|
515
558
|
self,
|
|
516
559
|
name: str = "Bundle",
|
|
@@ -686,6 +729,24 @@ class _SocketValueItemFactory(_TypedItemFactory):
|
|
|
686
729
|
"MaterialSocket", self._declare(name, value, "MATERIAL", structure_type)
|
|
687
730
|
)
|
|
688
731
|
|
|
732
|
+
def font(
|
|
733
|
+
self,
|
|
734
|
+
name: str = "Font",
|
|
735
|
+
value: InputFont = None,
|
|
736
|
+
*,
|
|
737
|
+
structure_type: _SocketShapeStructureType = "AUTO",
|
|
738
|
+
) -> FontSocket:
|
|
739
|
+
return cast("FontSocket", self._declare(name, value, "FONT", structure_type))
|
|
740
|
+
|
|
741
|
+
def sound(
|
|
742
|
+
self,
|
|
743
|
+
name: str = "Sound",
|
|
744
|
+
value: InputSound = None,
|
|
745
|
+
*,
|
|
746
|
+
structure_type: _SocketShapeStructureType = "AUTO",
|
|
747
|
+
) -> SoundSocket:
|
|
748
|
+
return cast("SoundSocket", self._declare(name, value, "SOUND", structure_type))
|
|
749
|
+
|
|
689
750
|
def bundle(
|
|
690
751
|
self,
|
|
691
752
|
name: str = "Bundle",
|
|
@@ -33,6 +33,7 @@ from .socket import (
|
|
|
33
33
|
CollectionSocket,
|
|
34
34
|
ColorSocket,
|
|
35
35
|
FloatSocket,
|
|
36
|
+
FontSocket,
|
|
36
37
|
GeometrySocket,
|
|
37
38
|
ImageSocket,
|
|
38
39
|
IntegerSocket,
|
|
@@ -43,6 +44,7 @@ from .socket import (
|
|
|
43
44
|
RotationSocket,
|
|
44
45
|
ShaderSocket,
|
|
45
46
|
Socket,
|
|
47
|
+
SoundSocket,
|
|
46
48
|
StringSocket,
|
|
47
49
|
VectorSocket,
|
|
48
50
|
)
|
|
@@ -518,6 +520,46 @@ class SocketContext:
|
|
|
518
520
|
)
|
|
519
521
|
return self._wrap(MaterialSocket, iface)
|
|
520
522
|
|
|
523
|
+
def font(
|
|
524
|
+
self,
|
|
525
|
+
name: str = "Font",
|
|
526
|
+
default_value: bpy.types.VectorFont | None = None,
|
|
527
|
+
description: str = "",
|
|
528
|
+
*,
|
|
529
|
+
optional_label: bool = False,
|
|
530
|
+
hide_value: bool = False,
|
|
531
|
+
hide_in_modifier: bool = False,
|
|
532
|
+
) -> FontSocket:
|
|
533
|
+
iface = self._add_socket("NodeSocketFont", name, description)
|
|
534
|
+
self._set_props(
|
|
535
|
+
iface,
|
|
536
|
+
default_value=default_value,
|
|
537
|
+
optional_label=optional_label,
|
|
538
|
+
hide_value=hide_value,
|
|
539
|
+
hide_in_modifier=hide_in_modifier,
|
|
540
|
+
)
|
|
541
|
+
return self._wrap(FontSocket, iface)
|
|
542
|
+
|
|
543
|
+
def sound(
|
|
544
|
+
self,
|
|
545
|
+
name: str = "Sound",
|
|
546
|
+
default_value: bpy.types.Sound | None = None,
|
|
547
|
+
description: str = "",
|
|
548
|
+
*,
|
|
549
|
+
optional_label: bool = False,
|
|
550
|
+
hide_value: bool = False,
|
|
551
|
+
hide_in_modifier: bool = False,
|
|
552
|
+
) -> SoundSocket:
|
|
553
|
+
iface = self._add_socket("NodeSocketSound", name, description)
|
|
554
|
+
self._set_props(
|
|
555
|
+
iface,
|
|
556
|
+
default_value=default_value,
|
|
557
|
+
optional_label=optional_label,
|
|
558
|
+
hide_value=hide_value,
|
|
559
|
+
hide_in_modifier=hide_in_modifier,
|
|
560
|
+
)
|
|
561
|
+
return self._wrap(SoundSocket, iface)
|
|
562
|
+
|
|
521
563
|
def bundle(
|
|
522
564
|
self,
|
|
523
565
|
name: str = "Bundle",
|
|
@@ -436,6 +436,8 @@ _INTERFACE_TYPE_METHOD: dict[str, str] = {
|
|
|
436
436
|
"NodeSocketCollection": "collection",
|
|
437
437
|
"NodeSocketImage": "image",
|
|
438
438
|
"NodeSocketMaterial": "material",
|
|
439
|
+
"NodeSocketFont": "font",
|
|
440
|
+
"NodeSocketSound": "sound",
|
|
439
441
|
"NodeSocketBundle": "bundle",
|
|
440
442
|
"NodeSocketClosure": "closure",
|
|
441
443
|
"NodeSocketShader": "shader",
|
|
@@ -448,6 +450,8 @@ _NO_DEFAULT_VALUE_TYPES = frozenset(
|
|
|
448
450
|
"NodeSocketCollection",
|
|
449
451
|
"NodeSocketImage",
|
|
450
452
|
"NodeSocketMaterial",
|
|
453
|
+
"NodeSocketFont",
|
|
454
|
+
"NodeSocketSound",
|
|
451
455
|
"NodeSocketBundle",
|
|
452
456
|
"NodeSocketClosure",
|
|
453
457
|
"NodeSocketShader",
|
|
@@ -3875,6 +3879,8 @@ _SWITCH_FACTORY_NAMES = {
|
|
|
3875
3879
|
"BUNDLE": "bundle",
|
|
3876
3880
|
"CLOSURE": "closure",
|
|
3877
3881
|
"SHADER": "shader",
|
|
3882
|
+
"FONT": "font",
|
|
3883
|
+
"SOUND": "sound",
|
|
3878
3884
|
}
|
|
3879
3885
|
|
|
3880
3886
|
|
|
@@ -3904,6 +3910,7 @@ def _emit_menu_switch(node, ctx: EmitContext) -> Expr | _Val | None:
|
|
|
3904
3910
|
"""MenuSwitch emits the factory dict form
|
|
3905
3911
|
``g.MenuSwitch.geometry(menu, {"Name": value, ...})`` — the plain
|
|
3906
3912
|
constructor's per-socket kwargs cannot recreate the enum item names.
|
|
3913
|
+
An item with a tooltip emits the ``(value, description)`` pair form.
|
|
3907
3914
|
Each tree type has its own MenuSwitch class (with tree-specific factories
|
|
3908
3915
|
such as ``shader``), so the alias follows the tree being exported."""
|
|
3909
3916
|
factory = _SWITCH_FACTORY_NAMES.get(node.data_type)
|
|
@@ -3911,7 +3918,14 @@ def _emit_menu_switch(node, ctx: EmitContext) -> Expr | _Val | None:
|
|
|
3911
3918
|
return None
|
|
3912
3919
|
alias = _TREE_ALIAS.get(ctx.node_tree.bl_idname, "g")
|
|
3913
3920
|
ctx.used_aliases.add(alias)
|
|
3914
|
-
|
|
3921
|
+
item_exprs: dict[str, Expr] = {}
|
|
3922
|
+
for (name, expr), item in zip(
|
|
3923
|
+
_switch_item_exprs(node, ctx, "Menu"), node.enum_items
|
|
3924
|
+
):
|
|
3925
|
+
if item.description:
|
|
3926
|
+
expr = TupleExpr([expr, Lit(item.description)])
|
|
3927
|
+
item_exprs[name] = expr
|
|
3928
|
+
items = DictExpr(item_exprs)
|
|
3915
3929
|
menu_link = ctx.input_link(node, "Menu")
|
|
3916
3930
|
if menu_link is not None:
|
|
3917
3931
|
return Call(
|
|
@@ -30,7 +30,7 @@ from ...types import (
|
|
|
30
30
|
InputString,
|
|
31
31
|
InputVector,
|
|
32
32
|
)
|
|
33
|
-
from ..geometry.manual import Float, Frame, _MenuSwitchBase
|
|
33
|
+
from ..geometry.manual import Float, Frame, MenuItems, _MenuSwitchBase
|
|
34
34
|
|
|
35
35
|
__all__ = ["Float", "Frame", "MenuSwitch", "tree"]
|
|
36
36
|
|
|
@@ -52,43 +52,43 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
52
52
|
|
|
53
53
|
@classmethod
|
|
54
54
|
def float(
|
|
55
|
-
cls, menu: InputMenu = None, items:
|
|
55
|
+
cls, menu: InputMenu = None, items: MenuItems[InputFloat] | None = None
|
|
56
56
|
) -> "MenuSwitch[FloatSocket]":
|
|
57
57
|
return MenuSwitch(menu, items, data_type="FLOAT")
|
|
58
58
|
|
|
59
59
|
@classmethod
|
|
60
60
|
def integer(
|
|
61
|
-
cls, menu: InputMenu = None, items:
|
|
61
|
+
cls, menu: InputMenu = None, items: MenuItems[InputInteger] | None = None
|
|
62
62
|
) -> "MenuSwitch[IntegerSocket]":
|
|
63
63
|
return MenuSwitch(menu, items, data_type="INT")
|
|
64
64
|
|
|
65
65
|
@classmethod
|
|
66
66
|
def boolean(
|
|
67
|
-
cls, menu: InputMenu = None, items:
|
|
67
|
+
cls, menu: InputMenu = None, items: MenuItems[InputBoolean] | None = None
|
|
68
68
|
) -> "MenuSwitch[BooleanSocket]":
|
|
69
69
|
return MenuSwitch(menu, items, data_type="BOOLEAN")
|
|
70
70
|
|
|
71
71
|
@classmethod
|
|
72
72
|
def vector(
|
|
73
|
-
cls, menu: InputMenu = None, items:
|
|
73
|
+
cls, menu: InputMenu = None, items: MenuItems[InputVector] | None = None
|
|
74
74
|
) -> "MenuSwitch[VectorSocket]":
|
|
75
75
|
return MenuSwitch(menu, items, data_type="VECTOR")
|
|
76
76
|
|
|
77
77
|
@classmethod
|
|
78
78
|
def color(
|
|
79
|
-
cls, menu: InputMenu = None, items:
|
|
79
|
+
cls, menu: InputMenu = None, items: MenuItems[InputColor] | None = None
|
|
80
80
|
) -> "MenuSwitch[ColorSocket]":
|
|
81
81
|
return MenuSwitch(menu, items, data_type="RGBA")
|
|
82
82
|
|
|
83
83
|
@classmethod
|
|
84
84
|
def string(
|
|
85
|
-
cls, menu: InputMenu = None, items:
|
|
85
|
+
cls, menu: InputMenu = None, items: MenuItems[InputString] | None = None
|
|
86
86
|
) -> "MenuSwitch[StringSocket]":
|
|
87
87
|
return MenuSwitch(menu, items, data_type="STRING")
|
|
88
88
|
|
|
89
89
|
@classmethod
|
|
90
90
|
def menu(
|
|
91
|
-
cls, menu: InputMenu = None, items:
|
|
91
|
+
cls, menu: InputMenu = None, items: MenuItems[InputMenu] | None = None
|
|
92
92
|
) -> "MenuSwitch[MenuSocket]":
|
|
93
93
|
return MenuSwitch(menu, items, data_type="MENU")
|
|
94
94
|
|
|
@@ -51,6 +51,7 @@ from ...builder import Socket as SocketLinker
|
|
|
51
51
|
from ...builder._registry import _wrap_socket
|
|
52
52
|
from ...builder.items import (
|
|
53
53
|
GridItem,
|
|
54
|
+
MenuItem,
|
|
54
55
|
_apply_item_value,
|
|
55
56
|
_FieldItemFactory,
|
|
56
57
|
_socket_for_item,
|
|
@@ -128,6 +129,9 @@ __all__ = (
|
|
|
128
129
|
"IndexSwitch",
|
|
129
130
|
"JoinGeometry",
|
|
130
131
|
"JoinStrings",
|
|
132
|
+
# "MenuItems" is deliberately not exported: quartodoc cannot document a
|
|
133
|
+
# PEP 695 `type` alias (griffe Kind.TYPE_ALIAS); import it from this
|
|
134
|
+
# module directly for annotations.
|
|
131
135
|
"MenuSwitch",
|
|
132
136
|
"MeshBoolean",
|
|
133
137
|
"RepeatInput",
|
|
@@ -1423,6 +1427,18 @@ class IndexSwitch[T: BaseSocket](ItemsMixin, BaseNode):
|
|
|
1423
1427
|
) -> "IndexSwitch[ClosureSocket]":
|
|
1424
1428
|
return IndexSwitch(index=index, items=items, data_type="CLOSURE")
|
|
1425
1429
|
|
|
1430
|
+
@classmethod
|
|
1431
|
+
def font(
|
|
1432
|
+
cls, index: InputInteger = 0, items: Iterable[InputFont] = ()
|
|
1433
|
+
) -> "IndexSwitch[FontSocket]":
|
|
1434
|
+
return IndexSwitch(index=index, items=items, data_type="FONT")
|
|
1435
|
+
|
|
1436
|
+
@classmethod
|
|
1437
|
+
def sound(
|
|
1438
|
+
cls, index: InputInteger = 0, items: Iterable[InputSound] = ()
|
|
1439
|
+
) -> "IndexSwitch[SoundSocket]":
|
|
1440
|
+
return IndexSwitch(index=index, items=items, data_type="SOUND")
|
|
1441
|
+
|
|
1426
1442
|
class _Inputs(SocketAccessor):
|
|
1427
1443
|
index: IntegerSocket
|
|
1428
1444
|
|
|
@@ -1501,6 +1517,22 @@ class IndexSwitch[T: BaseSocket](ItemsMixin, BaseNode):
|
|
|
1501
1517
|
self.node.data_type = value
|
|
1502
1518
|
|
|
1503
1519
|
|
|
1520
|
+
type MenuItems[V] = Mapping[str, None | V | tuple[V | None, str]]
|
|
1521
|
+
"""Menu Switch ``items`` mapping: item name → value, where the value may be
|
|
1522
|
+
a ``(value, description)`` pair to also set the item's tooltip."""
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
def _split_menu_item(
|
|
1526
|
+
value: InputAny | tuple[InputAny, str],
|
|
1527
|
+
) -> tuple[InputAny, str | None]:
|
|
1528
|
+
"""Split a ``(value, description)`` menu item pair. A 2-tuple whose
|
|
1529
|
+
second element is a string can never be a socket default value, so the
|
|
1530
|
+
form is unambiguous."""
|
|
1531
|
+
if isinstance(value, tuple) and len(value) == 2 and isinstance(value[1], str):
|
|
1532
|
+
return value[0], value[1]
|
|
1533
|
+
return cast("InputAny", value), None
|
|
1534
|
+
|
|
1535
|
+
|
|
1504
1536
|
class _MenuSwitchBase[T: BaseSocket](ItemsMixin, BaseNode):
|
|
1505
1537
|
"""Base class for MenuSwitch nodes across all tree types."""
|
|
1506
1538
|
|
|
@@ -1525,30 +1557,42 @@ class _MenuSwitchBase[T: BaseSocket](ItemsMixin, BaseNode):
|
|
|
1525
1557
|
def __init__(
|
|
1526
1558
|
self,
|
|
1527
1559
|
menu: InputMenu = None,
|
|
1528
|
-
items:
|
|
1560
|
+
items: MenuItems[InputAny] | None = None,
|
|
1529
1561
|
*,
|
|
1530
1562
|
data_type: SOCKET_TYPES = "FLOAT",
|
|
1531
1563
|
):
|
|
1532
1564
|
super().__init__()
|
|
1533
1565
|
self.data_type = data_type
|
|
1534
1566
|
self.node.enum_items.clear()
|
|
1535
|
-
|
|
1567
|
+
# a plain string `menu` is an explicit selection; otherwise the
|
|
1568
|
+
# selection defaults to the first item
|
|
1569
|
+
self._explicit_selection = isinstance(menu, str)
|
|
1536
1570
|
self._link_args(**(items or {}))
|
|
1537
|
-
self.
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if self.node.enum_items and not isinstance(menu, str):
|
|
1571
|
+
if isinstance(menu, str) and not self.node.enum_items:
|
|
1572
|
+
# a selection named before any items exist (they will be added via
|
|
1573
|
+
# item()) can't be set yet; defer it to context exit
|
|
1542
1574
|
assert self.node.inputs is not None
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1575
|
+
self.tree._menu_defaults.append(
|
|
1576
|
+
_MenuDefault(self.node.inputs["Menu"], menu)
|
|
1577
|
+
)
|
|
1578
|
+
else:
|
|
1579
|
+
self._establish_links(Menu=menu)
|
|
1580
|
+
|
|
1581
|
+
if self.node.enum_items and not self._explicit_selection:
|
|
1582
|
+
self._default_selection_to_first()
|
|
1583
|
+
|
|
1584
|
+
def _default_selection_to_first(self) -> None:
|
|
1585
|
+
"""Default the menu selection to the first enum item."""
|
|
1586
|
+
assert self.node.inputs is not None
|
|
1587
|
+
try:
|
|
1588
|
+
menu_socket = self.node.inputs["Menu"]
|
|
1589
|
+
menu_socket.default_value = self.node.enum_items[0].name
|
|
1590
|
+
except TypeError: # pragma: no cover - rare Blender enum-refresh quirk
|
|
1591
|
+
# the socket is a NodeSocketMenu whose enum hasn't refreshed yet, so
|
|
1592
|
+
# the default_value isn't settable here; defer it to context exit.
|
|
1593
|
+
self.tree._menu_defaults.append(
|
|
1594
|
+
_MenuDefault(self.node.inputs["Menu"], self.node.enum_items[0].name)
|
|
1595
|
+
)
|
|
1552
1596
|
|
|
1553
1597
|
@property
|
|
1554
1598
|
def _socket_data_types(self) -> tuple[str, ...]:
|
|
@@ -1560,24 +1604,57 @@ class _MenuSwitchBase[T: BaseSocket](ItemsMixin, BaseNode):
|
|
|
1560
1604
|
# menu items are untyped; .new() takes only a name
|
|
1561
1605
|
return self._items.new(name)
|
|
1562
1606
|
|
|
1563
|
-
def _link_args(self, **kwargs: InputAny):
|
|
1607
|
+
def _link_args(self, **kwargs: InputAny | tuple[InputAny, str]):
|
|
1564
1608
|
for key, value in kwargs.items():
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1609
|
+
value, description = _split_menu_item(value)
|
|
1610
|
+
item = self._new_item(key, self.data_type)
|
|
1611
|
+
if description:
|
|
1612
|
+
item.description = description
|
|
1613
|
+
self._apply_item_input(self._item_socket(item), value)
|
|
1614
|
+
|
|
1615
|
+
def _apply_item_input(self, socket: NodeSocket, value: InputAny) -> None:
|
|
1616
|
+
if value is None:
|
|
1617
|
+
return # item declared but left unlinked
|
|
1618
|
+
if _is_default_value(value):
|
|
1619
|
+
if isinstance(socket, bpy.types.NodeSocketMenu) and isinstance(value, str):
|
|
1620
|
+
# the socket is a NodeSocketMenu, but the default_value is not settable
|
|
1621
|
+
# until the full tree is built and menu items are known. We need to defer
|
|
1622
|
+
# the setting of the default values until after tree construction.
|
|
1623
|
+
self.tree._menu_defaults.append(_MenuDefault(socket, value))
|
|
1578
1624
|
else:
|
|
1579
|
-
|
|
1580
|
-
|
|
1625
|
+
socket.default_value = value # ty: ignore[unresolved-attribute]
|
|
1626
|
+
else:
|
|
1627
|
+
source = self._source_socket(value) # type: ignore
|
|
1628
|
+
self._link(source, socket)
|
|
1629
|
+
|
|
1630
|
+
def item(
|
|
1631
|
+
self,
|
|
1632
|
+
name: str,
|
|
1633
|
+
value: InputAny | tuple[InputAny, str] = None,
|
|
1634
|
+
*,
|
|
1635
|
+
description: str | None = None,
|
|
1636
|
+
) -> MenuItem[T]:
|
|
1637
|
+
"""Declare a menu item and return its handle.
|
|
1638
|
+
|
|
1639
|
+
``value`` may be a linkable (linked into the item's input socket), a
|
|
1640
|
+
plain default value, or a ``(value, description)`` pair; omit it to
|
|
1641
|
+
declare the item unlinked. ``description`` sets the tooltip Blender
|
|
1642
|
+
shows for the item in the menu.
|
|
1643
|
+
|
|
1644
|
+
Unless the menu selection was set explicitly, declaring the first
|
|
1645
|
+
item also defaults the selection to it (as the constructor does).
|
|
1646
|
+
"""
|
|
1647
|
+
value, pair_description = _split_menu_item(value)
|
|
1648
|
+
if description is None:
|
|
1649
|
+
description = pair_description
|
|
1650
|
+
bpy_item = self._new_item(name, self.data_type)
|
|
1651
|
+
if description:
|
|
1652
|
+
bpy_item.description = description
|
|
1653
|
+
handle = cast("MenuItem[T]", MenuItem(self, bpy_item))
|
|
1654
|
+
self._apply_item_input(self._item_socket(bpy_item), value)
|
|
1655
|
+
if len(self.node.enum_items) == 1 and not self._explicit_selection:
|
|
1656
|
+
self._default_selection_to_first()
|
|
1657
|
+
return handle
|
|
1581
1658
|
|
|
1582
1659
|
def is_selected(self, name: str) -> BooleanSocket:
|
|
1583
1660
|
"""Gets the boolean output socket that is True when the named menu item is selected.
|
|
@@ -1616,7 +1693,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1616
1693
|
def float(
|
|
1617
1694
|
cls,
|
|
1618
1695
|
menu: InputMenu = None,
|
|
1619
|
-
items:
|
|
1696
|
+
items: MenuItems[InputFloat] | None = None,
|
|
1620
1697
|
) -> "MenuSwitch[FloatSocket]":
|
|
1621
1698
|
return MenuSwitch(menu, items, data_type="FLOAT")
|
|
1622
1699
|
|
|
@@ -1624,7 +1701,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1624
1701
|
def integer(
|
|
1625
1702
|
cls,
|
|
1626
1703
|
menu: InputMenu = None,
|
|
1627
|
-
items:
|
|
1704
|
+
items: MenuItems[InputInteger] | None = None,
|
|
1628
1705
|
) -> "MenuSwitch[IntegerSocket]":
|
|
1629
1706
|
return MenuSwitch(menu, items, data_type="INT")
|
|
1630
1707
|
|
|
@@ -1632,7 +1709,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1632
1709
|
def boolean(
|
|
1633
1710
|
cls,
|
|
1634
1711
|
menu: InputMenu = None,
|
|
1635
|
-
items:
|
|
1712
|
+
items: MenuItems[InputBoolean] | None = None,
|
|
1636
1713
|
) -> "MenuSwitch[BooleanSocket]":
|
|
1637
1714
|
return MenuSwitch(menu, items, data_type="BOOLEAN")
|
|
1638
1715
|
|
|
@@ -1640,7 +1717,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1640
1717
|
def vector(
|
|
1641
1718
|
cls,
|
|
1642
1719
|
menu: InputMenu = None,
|
|
1643
|
-
items:
|
|
1720
|
+
items: MenuItems[InputVector] | None = None,
|
|
1644
1721
|
) -> "MenuSwitch[VectorSocket]":
|
|
1645
1722
|
return MenuSwitch(menu, items, data_type="VECTOR")
|
|
1646
1723
|
|
|
@@ -1648,7 +1725,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1648
1725
|
def color(
|
|
1649
1726
|
cls,
|
|
1650
1727
|
menu: InputMenu = None,
|
|
1651
|
-
items:
|
|
1728
|
+
items: MenuItems[InputColor] | None = None,
|
|
1652
1729
|
) -> "MenuSwitch[ColorSocket]":
|
|
1653
1730
|
return MenuSwitch(menu, items, data_type="RGBA")
|
|
1654
1731
|
|
|
@@ -1656,7 +1733,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1656
1733
|
def rotation(
|
|
1657
1734
|
cls,
|
|
1658
1735
|
menu: InputMenu = None,
|
|
1659
|
-
items:
|
|
1736
|
+
items: MenuItems[InputRotation] | None = None,
|
|
1660
1737
|
) -> "MenuSwitch[RotationSocket]":
|
|
1661
1738
|
return MenuSwitch(menu, items, data_type="ROTATION")
|
|
1662
1739
|
|
|
@@ -1664,7 +1741,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1664
1741
|
def matrix(
|
|
1665
1742
|
cls,
|
|
1666
1743
|
menu: InputMenu = None,
|
|
1667
|
-
items:
|
|
1744
|
+
items: MenuItems[InputMatrix] | None = None,
|
|
1668
1745
|
) -> "MenuSwitch[MatrixSocket]":
|
|
1669
1746
|
return MenuSwitch(menu, items, data_type="MATRIX")
|
|
1670
1747
|
|
|
@@ -1672,7 +1749,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1672
1749
|
def string(
|
|
1673
1750
|
cls,
|
|
1674
1751
|
menu: InputMenu = None,
|
|
1675
|
-
items:
|
|
1752
|
+
items: MenuItems[InputString] | None = None,
|
|
1676
1753
|
) -> "MenuSwitch[StringSocket]":
|
|
1677
1754
|
return MenuSwitch(menu, items, data_type="STRING")
|
|
1678
1755
|
|
|
@@ -1680,7 +1757,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1680
1757
|
def menu(
|
|
1681
1758
|
cls,
|
|
1682
1759
|
menu: InputMenu = None,
|
|
1683
|
-
items:
|
|
1760
|
+
items: MenuItems[InputMenu] | None = None,
|
|
1684
1761
|
) -> "MenuSwitch[MenuSocket]":
|
|
1685
1762
|
return MenuSwitch(menu, items, data_type="MENU")
|
|
1686
1763
|
|
|
@@ -1688,7 +1765,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1688
1765
|
def object(
|
|
1689
1766
|
cls,
|
|
1690
1767
|
menu: InputMenu = None,
|
|
1691
|
-
items:
|
|
1768
|
+
items: MenuItems[InputObject] | None = None,
|
|
1692
1769
|
) -> "MenuSwitch[ObjectSocket]":
|
|
1693
1770
|
return MenuSwitch(menu, items, data_type="OBJECT")
|
|
1694
1771
|
|
|
@@ -1696,7 +1773,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1696
1773
|
def geometry(
|
|
1697
1774
|
cls,
|
|
1698
1775
|
menu: InputMenu = None,
|
|
1699
|
-
items:
|
|
1776
|
+
items: MenuItems[InputGeometry] | None = None,
|
|
1700
1777
|
) -> "MenuSwitch[GeometrySocket]":
|
|
1701
1778
|
return MenuSwitch(menu, items, data_type="GEOMETRY")
|
|
1702
1779
|
|
|
@@ -1704,7 +1781,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1704
1781
|
def collection(
|
|
1705
1782
|
cls,
|
|
1706
1783
|
menu: InputMenu = None,
|
|
1707
|
-
items:
|
|
1784
|
+
items: MenuItems[InputCollection] | None = None,
|
|
1708
1785
|
) -> "MenuSwitch[CollectionSocket]":
|
|
1709
1786
|
return MenuSwitch(menu, items, data_type="COLLECTION")
|
|
1710
1787
|
|
|
@@ -1712,7 +1789,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1712
1789
|
def image(
|
|
1713
1790
|
cls,
|
|
1714
1791
|
menu: InputMenu = None,
|
|
1715
|
-
items:
|
|
1792
|
+
items: MenuItems[InputImage] | None = None,
|
|
1716
1793
|
) -> "MenuSwitch[ImageSocket]":
|
|
1717
1794
|
return MenuSwitch(menu, items, data_type="IMAGE")
|
|
1718
1795
|
|
|
@@ -1720,7 +1797,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1720
1797
|
def material(
|
|
1721
1798
|
cls,
|
|
1722
1799
|
menu: InputMenu = None,
|
|
1723
|
-
items:
|
|
1800
|
+
items: MenuItems[InputMaterial] | None = None,
|
|
1724
1801
|
) -> "MenuSwitch[MaterialSocket]":
|
|
1725
1802
|
return MenuSwitch(menu, items, data_type="MATERIAL")
|
|
1726
1803
|
|
|
@@ -1728,7 +1805,7 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1728
1805
|
def bundle(
|
|
1729
1806
|
cls,
|
|
1730
1807
|
menu: InputMenu = None,
|
|
1731
|
-
items:
|
|
1808
|
+
items: MenuItems[InputBundle] | None = None,
|
|
1732
1809
|
) -> "MenuSwitch[BundleSocket]":
|
|
1733
1810
|
return MenuSwitch(menu, items, data_type="BUNDLE")
|
|
1734
1811
|
|
|
@@ -1736,10 +1813,26 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
1736
1813
|
def closure(
|
|
1737
1814
|
cls,
|
|
1738
1815
|
menu: InputMenu = None,
|
|
1739
|
-
items:
|
|
1816
|
+
items: MenuItems[InputClosure] | None = None,
|
|
1740
1817
|
) -> "MenuSwitch[ClosureSocket]":
|
|
1741
1818
|
return MenuSwitch(menu, items, data_type="CLOSURE")
|
|
1742
1819
|
|
|
1820
|
+
@classmethod
|
|
1821
|
+
def font(
|
|
1822
|
+
cls,
|
|
1823
|
+
menu: InputMenu = None,
|
|
1824
|
+
items: dict[str, InputFont] | None = None,
|
|
1825
|
+
) -> "MenuSwitch[FontSocket]":
|
|
1826
|
+
return MenuSwitch(menu, items, data_type="FONT")
|
|
1827
|
+
|
|
1828
|
+
@classmethod
|
|
1829
|
+
def sound(
|
|
1830
|
+
cls,
|
|
1831
|
+
menu: InputMenu = None,
|
|
1832
|
+
items: dict[str, InputSound] | None = None,
|
|
1833
|
+
) -> "MenuSwitch[SoundSocket]":
|
|
1834
|
+
return MenuSwitch(menu, items, data_type="SOUND")
|
|
1835
|
+
|
|
1743
1836
|
|
|
1744
1837
|
class CaptureAttribute(ItemsMixin, BaseNode):
|
|
1745
1838
|
"""
|
|
@@ -22,6 +22,7 @@ from ...builder import (
|
|
|
22
22
|
CollectionSocket,
|
|
23
23
|
ColorSocket,
|
|
24
24
|
FloatSocket,
|
|
25
|
+
FontSocket,
|
|
25
26
|
GeometrySocket,
|
|
26
27
|
ImageSocket,
|
|
27
28
|
IntegerSocket,
|
|
@@ -32,6 +33,7 @@ from ...builder import (
|
|
|
32
33
|
MenuSocket,
|
|
33
34
|
ObjectSocket,
|
|
34
35
|
RotationSocket,
|
|
36
|
+
SoundSocket,
|
|
35
37
|
StringSocket,
|
|
36
38
|
VectorSocket,
|
|
37
39
|
)
|
|
@@ -48,6 +50,7 @@ from ...types import (
|
|
|
48
50
|
InputCollection,
|
|
49
51
|
InputColor,
|
|
50
52
|
InputFloat,
|
|
53
|
+
InputFont,
|
|
51
54
|
InputGeometry,
|
|
52
55
|
InputImage,
|
|
53
56
|
InputInteger,
|
|
@@ -57,6 +60,7 @@ from ...types import (
|
|
|
57
60
|
InputMenu,
|
|
58
61
|
InputObject,
|
|
59
62
|
InputRotation,
|
|
63
|
+
InputSound,
|
|
60
64
|
InputString,
|
|
61
65
|
InputVector,
|
|
62
66
|
_AttributeDomains,
|
|
@@ -331,6 +335,16 @@ class _RepeatZoneItems(_StateZoneItems):
|
|
|
331
335
|
) -> "ZoneItem[ClosureSocket]":
|
|
332
336
|
return cast("ZoneItem[ClosureSocket]", self._declare(name, initial, "CLOSURE"))
|
|
333
337
|
|
|
338
|
+
def font(
|
|
339
|
+
self, name: str = "Font", initial: InputFont = None
|
|
340
|
+
) -> "ZoneItem[FontSocket]":
|
|
341
|
+
return cast("ZoneItem[FontSocket]", self._declare(name, initial, "FONT"))
|
|
342
|
+
|
|
343
|
+
def sound(
|
|
344
|
+
self, name: str = "Sound", initial: InputSound = None
|
|
345
|
+
) -> "ZoneItem[SoundSocket]":
|
|
346
|
+
return cast("ZoneItem[SoundSocket]", self._declare(name, initial, "SOUND"))
|
|
347
|
+
|
|
334
348
|
|
|
335
349
|
class BaseSimulationZone(BaseZone):
|
|
336
350
|
_items_collection = "state_items"
|
|
@@ -419,6 +433,8 @@ class BaseRepeatZone(BaseZone):
|
|
|
419
433
|
"MATERIAL",
|
|
420
434
|
"BUNDLE",
|
|
421
435
|
"CLOSURE",
|
|
436
|
+
"FONT",
|
|
437
|
+
"SOUND",
|
|
422
438
|
)
|
|
423
439
|
|
|
424
440
|
_type_map: ClassVar[dict[str, str]] = {"VALUE": "FLOAT"}
|
|
@@ -30,7 +30,7 @@ from ...types import (
|
|
|
30
30
|
InputVector,
|
|
31
31
|
)
|
|
32
32
|
from ..geometry import Frame, RepeatInput, RepeatOutput, RepeatZone
|
|
33
|
-
from ..geometry.manual import Float, _MenuSwitchBase
|
|
33
|
+
from ..geometry.manual import Float, MenuItems, _MenuSwitchBase
|
|
34
34
|
|
|
35
35
|
__all__ = [
|
|
36
36
|
"Attribute",
|
|
@@ -74,55 +74,55 @@ class MenuSwitch[T: BaseSocket](_MenuSwitchBase[T]):
|
|
|
74
74
|
|
|
75
75
|
@classmethod
|
|
76
76
|
def float(
|
|
77
|
-
cls, menu: InputMenu = None, items:
|
|
77
|
+
cls, menu: InputMenu = None, items: MenuItems[InputFloat] | None = None
|
|
78
78
|
) -> "MenuSwitch[FloatSocket]":
|
|
79
79
|
return MenuSwitch(menu, items, data_type="FLOAT")
|
|
80
80
|
|
|
81
81
|
@classmethod
|
|
82
82
|
def integer(
|
|
83
|
-
cls, menu: InputMenu = None, items:
|
|
83
|
+
cls, menu: InputMenu = None, items: MenuItems[InputInteger] | None = None
|
|
84
84
|
) -> "MenuSwitch[IntegerSocket]":
|
|
85
85
|
return MenuSwitch(menu, items, data_type="INT")
|
|
86
86
|
|
|
87
87
|
@classmethod
|
|
88
88
|
def boolean(
|
|
89
|
-
cls, menu: InputMenu = None, items:
|
|
89
|
+
cls, menu: InputMenu = None, items: MenuItems[InputBoolean] | None = None
|
|
90
90
|
) -> "MenuSwitch[BooleanSocket]":
|
|
91
91
|
return MenuSwitch(menu, items, data_type="BOOLEAN")
|
|
92
92
|
|
|
93
93
|
@classmethod
|
|
94
94
|
def vector(
|
|
95
|
-
cls, menu: InputMenu = None, items:
|
|
95
|
+
cls, menu: InputMenu = None, items: MenuItems[InputVector] | None = None
|
|
96
96
|
) -> "MenuSwitch[VectorSocket]":
|
|
97
97
|
return MenuSwitch(menu, items, data_type="VECTOR")
|
|
98
98
|
|
|
99
99
|
@classmethod
|
|
100
100
|
def color(
|
|
101
|
-
cls, menu: InputMenu = None, items:
|
|
101
|
+
cls, menu: InputMenu = None, items: MenuItems[InputColor] | None = None
|
|
102
102
|
) -> "MenuSwitch[ColorSocket]":
|
|
103
103
|
return MenuSwitch(menu, items, data_type="RGBA")
|
|
104
104
|
|
|
105
105
|
@classmethod
|
|
106
106
|
def menu(
|
|
107
|
-
cls, menu: InputMenu = None, items:
|
|
107
|
+
cls, menu: InputMenu = None, items: MenuItems[InputMenu] | None = None
|
|
108
108
|
) -> "MenuSwitch[MenuSocket]":
|
|
109
109
|
return MenuSwitch(menu, items, data_type="MENU")
|
|
110
110
|
|
|
111
111
|
@classmethod
|
|
112
112
|
def closure(
|
|
113
|
-
cls, menu: InputMenu = None, items:
|
|
113
|
+
cls, menu: InputMenu = None, items: MenuItems[InputClosure] | None = None
|
|
114
114
|
) -> "MenuSwitch[ClosureSocket]":
|
|
115
115
|
return MenuSwitch(menu, items, data_type="CLOSURE")
|
|
116
116
|
|
|
117
117
|
@classmethod
|
|
118
118
|
def bundle(
|
|
119
|
-
cls, menu: InputMenu = None, items:
|
|
119
|
+
cls, menu: InputMenu = None, items: MenuItems[InputBundle] | None = None
|
|
120
120
|
) -> "MenuSwitch[BundleSocket]":
|
|
121
121
|
return MenuSwitch(menu, items, data_type="BUNDLE")
|
|
122
122
|
|
|
123
123
|
@classmethod
|
|
124
124
|
def shader(
|
|
125
|
-
cls, menu: InputMenu = None, items:
|
|
125
|
+
cls, menu: InputMenu = None, items: MenuItems[InputShader] | None = None
|
|
126
126
|
) -> "MenuSwitch[ShaderSocket]":
|
|
127
127
|
return MenuSwitch(menu, items, data_type="SHADER")
|
|
128
128
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|