nodebpy 0.3.1__tar.gz → 0.4.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.
Files changed (37) hide show
  1. {nodebpy-0.3.1 → nodebpy-0.4.0}/PKG-INFO +6 -56
  2. {nodebpy-0.3.1 → nodebpy-0.4.0}/README.md +4 -54
  3. {nodebpy-0.3.1 → nodebpy-0.4.0}/pyproject.toml +2 -2
  4. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/builder.py +17 -13
  5. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/__init__.py +2 -0
  6. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/graph.py +583 -0
  7. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/ordering.py +512 -0
  8. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/ranking.py +256 -0
  9. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/realize.py +231 -0
  10. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/stacking.py +313 -0
  11. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/structs.py +132 -0
  12. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +256 -0
  13. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/x_coords.py +211 -0
  14. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/arrange/y_coords.py +339 -0
  15. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/config.py +45 -0
  16. nodebpy-0.4.0/src/nodebpy/lib/nodearrange/utils.py +109 -0
  17. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/color.py +0 -1
  18. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/group.py +0 -1
  19. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/__init__.py +0 -0
  20. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/arrange.py +0 -0
  21. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/__init__.py +0 -0
  22. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/attribute.py +0 -0
  23. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/converter.py +0 -0
  24. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/experimental.py +0 -0
  25. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/geometry.py +0 -0
  26. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/grid.py +0 -0
  27. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/input.py +0 -0
  28. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/interface.py +0 -0
  29. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/manual.py +0 -0
  30. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/output.py +0 -0
  31. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/texture.py +0 -0
  32. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/vector.py +0 -0
  33. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/nodes/zone.py +0 -0
  34. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/screenshot.py +0 -0
  35. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/screenshot_subprocess.py +0 -0
  36. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/sockets.py +0 -0
  37. {nodebpy-0.3.1 → nodebpy-0.4.0}/src/nodebpy/types.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nodebpy
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: Build nodes in Blender with code
5
5
  Author: Brady Johnston
6
6
  Author-email: Brady Johnston <brady.johnston@me.com>
7
- Requires-Dist: arrangebpy>=0.1.0
7
+ Requires-Dist: networkx>=3.6.1
8
8
  Requires-Dist: bpy>=5.0.0 ; extra == 'bpy'
9
9
  Requires-Dist: fake-bpy-module>=20260113 ; extra == 'dev'
10
10
  Requires-Dist: jsondiff>=2.2.1 ; extra == 'dev'
@@ -60,18 +60,16 @@ be linked to the previous node via the inferred or specified socket.
60
60
  ``` python
61
61
  from nodebpy import TreeBuilder, nodes as n, sockets as s
62
62
 
63
- with TreeBuilder("AnotherTree") as tree:
63
+ with TreeBuilder("AnotherTree", collapse=True) as tree:
64
64
  with tree.inputs:
65
65
  count = s.SocketInt("Count", 10)
66
66
  with tree.outputs:
67
67
  instances = s.SocketGeometry("Instances")
68
68
 
69
69
  rotation = (
70
- n.RandomValue.vector(min=(-1, -1, -1), seed=2)
70
+ n.RandomValue.vector(min=-1, seed=2)
71
71
  >> n.AlignRotationToVector()
72
- >> n.RotateRotation(
73
- rotate_by=n.AxisAngleToRotation(angle=0.3), rotation_space="LOCAL"
74
- )
72
+ >> n.RotateRotation(rotate_by=n.AxisAngleToRotation(angle=0.3))
75
73
  )
76
74
 
77
75
  _ = (
@@ -86,57 +84,9 @@ with TreeBuilder("AnotherTree") as tree:
86
84
  >> n.InstanceOnPoints(n.Cube(), instance=...)
87
85
  >> instances
88
86
  )
89
-
90
- tree
91
- ```
92
-
93
- ``` mermaid
94
- graph LR
95
- N0("NodeGroupInput"):::default-node
96
- N1("RandomValue<br/><small>(-1,-1,-1) seed:2</small>"):::converter-node
97
- N2("RandomValue<br/><small>(-1,-1,-1)</small>"):::converter-node
98
- N3("AlignRotationToVector"):::converter-node
99
- N4("AxisAngleToRotation<br/><small>(0,0,1)</small>"):::converter-node
100
- N5("InputPosition"):::input-node
101
- N6("Points"):::geometry-node
102
- N7("MeshCube"):::geometry-node
103
- N8("RotateRotation"):::converter-node
104
- N9("VectorMath<br/><small>×2</small>"):::vector-node
105
- N10("InstanceOnPoints"):::geometry-node
106
- N11("VectorMath<br/><small>(0,0.2,0.3)</small>"):::vector-node
107
- N12("SetPosition<br/><small>+(0,0,0.1)</small>"):::geometry-node
108
- N13("MeshCube"):::geometry-node
109
- N14("RealizeInstances"):::geometry-node
110
- N15("InstanceOnPoints"):::geometry-node
111
- N16("NodeGroupOutput"):::default-node
112
- N1 -->|"Value>>Vector"| N3
113
- N4 -->|"Rotation>>Rotate By"| N8
114
- N3 -->|"Rotation>>Rotation"| N8
115
- N2 -->|"Value>>Position"| N6
116
- N0 -->|"Count>>Count"| N6
117
- N7 -->|"Mesh>>Instance"| N10
118
- N8 -->|"Rotation>>Rotation"| N10
119
- N6 -->|"Points>>Points"| N10
120
- N5 -->|"Position>>Vector"| N9
121
- N9 -->|"Vector>>Vector"| N11
122
- N11 -->|"Vector>>Position"| N12
123
- N10 -->|"Instances>>Geometry"| N12
124
- N12 -->|"Geometry>>Geometry"| N14
125
- N13 -->|"Mesh>>Points"| N15
126
- N14 -->|"Geometry>>Instance"| N15
127
- N15 -->|"Instances>>Instances"| N16
128
-
129
- classDef geometry-node fill:#e8f5f1,stroke:#3a7c49,stroke-width:2px
130
- classDef converter-node fill:#e6f1f7,stroke:#246283,stroke-width:2px
131
- classDef vector-node fill:#e9e9f5,stroke:#3C3C83,stroke-width:2px
132
- classDef texture-node fill:#fef3e6,stroke:#E66800,stroke-width:2px
133
- classDef shader-node fill:#fef0eb,stroke:#e67c52,stroke-width:2px
134
- classDef input-node fill:#f1f8ed,stroke:#7fb069,stroke-width:2px
135
- classDef output-node fill:#faf0ed,stroke:#c97659,stroke-width:2px
136
- classDef default-node fill:#f0f0f0,stroke:#5a5a5a,stroke-width:2px
137
87
  ```
138
88
 
139
- ![](docs/images/paste-2.png)
89
+ ![](docs/images/paste-1.png)
140
90
 
141
91
  # Design Considerations
142
92
 
@@ -36,18 +36,16 @@ be linked to the previous node via the inferred or specified socket.
36
36
  ``` python
37
37
  from nodebpy import TreeBuilder, nodes as n, sockets as s
38
38
 
39
- with TreeBuilder("AnotherTree") as tree:
39
+ with TreeBuilder("AnotherTree", collapse=True) as tree:
40
40
  with tree.inputs:
41
41
  count = s.SocketInt("Count", 10)
42
42
  with tree.outputs:
43
43
  instances = s.SocketGeometry("Instances")
44
44
 
45
45
  rotation = (
46
- n.RandomValue.vector(min=(-1, -1, -1), seed=2)
46
+ n.RandomValue.vector(min=-1, seed=2)
47
47
  >> n.AlignRotationToVector()
48
- >> n.RotateRotation(
49
- rotate_by=n.AxisAngleToRotation(angle=0.3), rotation_space="LOCAL"
50
- )
48
+ >> n.RotateRotation(rotate_by=n.AxisAngleToRotation(angle=0.3))
51
49
  )
52
50
 
53
51
  _ = (
@@ -62,57 +60,9 @@ with TreeBuilder("AnotherTree") as tree:
62
60
  >> n.InstanceOnPoints(n.Cube(), instance=...)
63
61
  >> instances
64
62
  )
65
-
66
- tree
67
- ```
68
-
69
- ``` mermaid
70
- graph LR
71
- N0("NodeGroupInput"):::default-node
72
- N1("RandomValue<br/><small>(-1,-1,-1) seed:2</small>"):::converter-node
73
- N2("RandomValue<br/><small>(-1,-1,-1)</small>"):::converter-node
74
- N3("AlignRotationToVector"):::converter-node
75
- N4("AxisAngleToRotation<br/><small>(0,0,1)</small>"):::converter-node
76
- N5("InputPosition"):::input-node
77
- N6("Points"):::geometry-node
78
- N7("MeshCube"):::geometry-node
79
- N8("RotateRotation"):::converter-node
80
- N9("VectorMath<br/><small>×2</small>"):::vector-node
81
- N10("InstanceOnPoints"):::geometry-node
82
- N11("VectorMath<br/><small>(0,0.2,0.3)</small>"):::vector-node
83
- N12("SetPosition<br/><small>+(0,0,0.1)</small>"):::geometry-node
84
- N13("MeshCube"):::geometry-node
85
- N14("RealizeInstances"):::geometry-node
86
- N15("InstanceOnPoints"):::geometry-node
87
- N16("NodeGroupOutput"):::default-node
88
- N1 -->|"Value>>Vector"| N3
89
- N4 -->|"Rotation>>Rotate By"| N8
90
- N3 -->|"Rotation>>Rotation"| N8
91
- N2 -->|"Value>>Position"| N6
92
- N0 -->|"Count>>Count"| N6
93
- N7 -->|"Mesh>>Instance"| N10
94
- N8 -->|"Rotation>>Rotation"| N10
95
- N6 -->|"Points>>Points"| N10
96
- N5 -->|"Position>>Vector"| N9
97
- N9 -->|"Vector>>Vector"| N11
98
- N11 -->|"Vector>>Position"| N12
99
- N10 -->|"Instances>>Geometry"| N12
100
- N12 -->|"Geometry>>Geometry"| N14
101
- N13 -->|"Mesh>>Points"| N15
102
- N14 -->|"Geometry>>Instance"| N15
103
- N15 -->|"Instances>>Instances"| N16
104
-
105
- classDef geometry-node fill:#e8f5f1,stroke:#3a7c49,stroke-width:2px
106
- classDef converter-node fill:#e6f1f7,stroke:#246283,stroke-width:2px
107
- classDef vector-node fill:#e9e9f5,stroke:#3C3C83,stroke-width:2px
108
- classDef texture-node fill:#fef3e6,stroke:#E66800,stroke-width:2px
109
- classDef shader-node fill:#fef0eb,stroke:#e67c52,stroke-width:2px
110
- classDef input-node fill:#f1f8ed,stroke:#7fb069,stroke-width:2px
111
- classDef output-node fill:#faf0ed,stroke:#c97659,stroke-width:2px
112
- classDef default-node fill:#f0f0f0,stroke:#5a5a5a,stroke-width:2px
113
63
  ```
114
64
 
115
- ![](docs/images/paste-2.png)
65
+ ![](docs/images/paste-1.png)
116
66
 
117
67
  # Design Considerations
118
68
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nodebpy"
3
- version = "0.3.1"
3
+ version = "0.4.0"
4
4
  description = "Build nodes in Blender with code"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -8,7 +8,7 @@ authors = [
8
8
  ]
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
11
- "arrangebpy>=0.1.0",
11
+ "networkx>=3.6.1",
12
12
  ]
13
13
 
14
14
  [project.scripts]
@@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, Any, ClassVar, Iterable, Literal
5
5
  if TYPE_CHECKING:
6
6
  from .nodes import Math, VectorMath
7
7
 
8
- import arrangebpy
9
8
  import bpy
10
9
  from bpy.types import (
11
10
  GeometryNodeTree,
@@ -14,6 +13,7 @@ from bpy.types import (
14
13
  NodeSocket,
15
14
  )
16
15
 
16
+ from .lib.nodearrange import arrange
17
17
  from .types import (
18
18
  LINKABLE,
19
19
  SOCKET_COMPATIBILITY,
@@ -117,12 +117,15 @@ class TreeBuilder:
117
117
  """Builder for creating Blender geometry node trees with a clean Python API."""
118
118
 
119
119
  _tree_contexts: ClassVar["list[TreeBuilder]"] = []
120
- # _active_tree: ClassVar["TreeBuilder | None"] = None
121
- # _previous_tree: ClassVar["list[TreeBuilder]"] = list()
122
120
  just_added: "Node | None" = None
121
+ collapse: bool = False
123
122
 
124
123
  def __init__(
125
- self, tree: GeometryNodeTree | str = "Geometry Nodes", arrange: bool = True
124
+ self,
125
+ tree: GeometryNodeTree | str = "Geometry Nodes",
126
+ *,
127
+ collapse: bool = False,
128
+ arrange: bool = True,
126
129
  ):
127
130
  if isinstance(tree, str):
128
131
  self.tree = bpy.data.node_groups.new(tree, "GeometryNodeTree")
@@ -134,6 +137,11 @@ class TreeBuilder:
134
137
  self.inputs = InputInterfaceContext(self)
135
138
  self.outputs = OutputInterfaceContext(self)
136
139
  self._arrange = arrange
140
+ self.collapse = collapse
141
+
142
+ @property
143
+ def nodes(self) -> Nodes:
144
+ return self.tree.nodes
137
145
 
138
146
  def activate_tree(self) -> None:
139
147
  """Make this tree the active tree for all new node creation."""
@@ -152,18 +160,12 @@ class TreeBuilder:
152
160
  self.arrange()
153
161
  self.deactivate_tree()
154
162
 
155
- @property
156
- def nodes(self) -> Nodes:
157
- return self.tree.nodes
158
-
159
163
  def __len__(self) -> int:
160
164
  return len(self.nodes)
161
165
 
162
166
  def arrange(self):
163
- settings = arrangebpy.LayoutSettings(
164
- horizontal_spacing=200, vertical_spacing=200, align_top_layer=True
165
- )
166
- arrangebpy.sugiyama_layout(self.tree, settings)
167
+ arrange.sugiyama.sugiyama_layout(self.tree)
168
+ arrange.sugiyama.config.reset()
167
169
 
168
170
  def _repr_markdown_(self) -> str | None:
169
171
  """
@@ -230,7 +232,9 @@ class TreeBuilder:
230
232
  return link
231
233
 
232
234
  def add(self, name: str) -> Node:
233
- return self.tree.nodes.new(name)
235
+ node = self.tree.nodes.new(name)
236
+ node.hide = self.collapse
237
+ return node
234
238
 
235
239
 
236
240
  class NodeBuilder:
@@ -0,0 +1,2 @@
1
+ # SPDX-License-Identifier: GPL-2.0-or-later
2
+ from .arrange import sugiyama