procfunc 0.30.1__tar.gz → 0.31.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.
- {procfunc-0.30.1/src/procfunc.egg-info → procfunc-0.31.0}/PKG-INFO +3 -3
- {procfunc-0.30.1 → procfunc-0.31.0}/README.md +1 -2
- {procfunc-0.30.1 → procfunc-0.31.0}/pyproject.toml +6 -2
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/__init__.py +2 -1
- procfunc-0.31.0/src/procfunc/cli.py +35 -0
- procfunc-0.31.0/src/procfunc/codegen/__init__.py +8 -0
- {procfunc-0.30.1/src/procfunc/transpiler → procfunc-0.31.0/src/procfunc/codegen}/codegen.py +11 -4
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/node.py +2 -9
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/__init__.py +5 -1
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/bindings_util.py +112 -2
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/bpy_node_info.py +7 -0
- procfunc-0.31.0/src/procfunc/nodes/color.py +334 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/compositor.py +125 -353
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/execute/construct_nodes.py +37 -6
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/execute/construct_special_cases.py +25 -14
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/execute/util.py +3 -3
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/func.py +55 -468
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/geo.py +195 -184
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/manifest.json +2508 -300
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/math.py +321 -140
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/shader.py +3 -880
- procfunc-0.31.0/src/procfunc/nodes/texture.py +686 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/types.py +0 -18
- procfunc-0.31.0/src/procfunc/ops/file.py +279 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/__init__.py +2 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transpiler/__init__.py +0 -6
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transpiler/bpy_to_computegraph.py +90 -32
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transpiler/main.py +85 -21
- {procfunc-0.30.1 → procfunc-0.31.0/src/procfunc.egg-info}/PKG-INFO +3 -3
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc.egg-info/SOURCES.txt +8 -3
- procfunc-0.31.0/src/procfunc.egg-info/entry_points.txt +2 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc.egg-info/requires.txt +1 -0
- procfunc-0.30.1/tests/test_dedup_names.py → procfunc-0.31.0/tests/test_codegen.py +1 -1
- {procfunc-0.30.1 → procfunc-0.31.0}/tests/test_ops.py +31 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/tests/test_trace.py +1 -1
- procfunc-0.30.1/src/procfunc/ops/file.py +0 -126
- {procfunc-0.30.1 → procfunc-0.31.0}/LICENSE.md +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/setup.cfg +0 -0
- {procfunc-0.30.1/src/procfunc/transpiler → procfunc-0.31.0/src/procfunc/codegen}/identifiers.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/color.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/__init__.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/compute_graph.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/operators_info.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/proxy.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/compute_graph/util.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/context.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/control.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/execute/execute.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/execute/infer_runtime_data_type.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/nodes/node_function.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/__init__.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/_util.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/addons.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/attr.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/collection.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/curve.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/manifest.json +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/mesh.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/modifier.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/object.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/primitives/__init__.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/primitives/camera.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/primitives/curve.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/primitives/light.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/primitives/mesh.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/ops/uv.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/random.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/tracer/__init__.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/tracer/decorator.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/tracer/patch.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/tracer/proxy.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/tracer/trace.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/cleanup.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/convert.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/distribution.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/extract_materials.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/infer_distribution.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/parameters.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/transforms/util.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/types.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/__init__.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/bpy_info.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/camera.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/keyframe.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/log.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/manifest.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/pytree.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc/util/teardown.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc.egg-info/dependency_links.txt +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/src/procfunc.egg-info/top_level.txt +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/tests/test_asset.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/tests/test_compute_graph.py +0 -0
- {procfunc-0.30.1 → procfunc-0.31.0}/tests/test_pytree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: procfunc
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.31.0
|
|
4
4
|
Summary: Function-Oriented Abstractions for Procedural 3D Generation in Python
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
Project-URL: Homepage, https://github.com/princeton-vl/procfunc
|
|
@@ -19,13 +19,13 @@ Requires-Dist: ty; extra == "dev"
|
|
|
19
19
|
Provides-Extra: docs
|
|
20
20
|
Requires-Dist: sphinx; extra == "docs"
|
|
21
21
|
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
22
|
+
Requires-Dist: sphinx-argparse; extra == "docs"
|
|
22
23
|
Dynamic: license-file
|
|
23
24
|
|
|
24
25
|
# ProcFunc: Function-Oriented Abstractions for Procedural 3D Generation in Python
|
|
25
26
|
|
|
26
27
|
[**Documentation**](#documentation)
|
|
27
28
|
| [**Research Paper**](https://arxiv.org/abs/2604.26943)
|
|
28
|
-
| [**Documentation**](https://procfunc.readthedocs.io)
|
|
29
29
|
| [**Transpiling**](#transpile-a-blender-file-to-procfunc-code)
|
|
30
30
|
| [**Experiments**](#experiments)
|
|
31
31
|
| [**Contributing**](#contributing)
|
|
@@ -62,7 +62,7 @@ Please create Github Issues for any bugs or unclear interfaces!
|
|
|
62
62
|
Convert a Blender geometry node tree into procfunc Python code by downloading our example blend and executing the transpiler:
|
|
63
63
|
```bash
|
|
64
64
|
wget https://raw.githubusercontent.com/princeton-vl/procfunc/main/examples/transpile_simple_chair/simple_chair.blend
|
|
65
|
-
uv run
|
|
65
|
+
uv run procfunc transpile simple_chair.blend --node_trees simple_chair --output transpiled_code.py
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
See the expected output in [`examples/transpile_simple_chair/transpiled_code.py`](examples/transpile_simple_chair/transpiled_code.py).
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
[**Documentation**](#documentation)
|
|
4
4
|
| [**Research Paper**](https://arxiv.org/abs/2604.26943)
|
|
5
|
-
| [**Documentation**](https://procfunc.readthedocs.io)
|
|
6
5
|
| [**Transpiling**](#transpile-a-blender-file-to-procfunc-code)
|
|
7
6
|
| [**Experiments**](#experiments)
|
|
8
7
|
| [**Contributing**](#contributing)
|
|
@@ -39,7 +38,7 @@ Please create Github Issues for any bugs or unclear interfaces!
|
|
|
39
38
|
Convert a Blender geometry node tree into procfunc Python code by downloading our example blend and executing the transpiler:
|
|
40
39
|
```bash
|
|
41
40
|
wget https://raw.githubusercontent.com/princeton-vl/procfunc/main/examples/transpile_simple_chair/simple_chair.blend
|
|
42
|
-
uv run
|
|
41
|
+
uv run procfunc transpile simple_chair.blend --node_trees simple_chair --output transpiled_code.py
|
|
43
42
|
```
|
|
44
43
|
|
|
45
44
|
See the expected output in [`examples/transpile_simple_chair/transpiled_code.py`](examples/transpile_simple_chair/transpiled_code.py).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "procfunc"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.31.0"
|
|
8
8
|
description = "Function-Oriented Abstractions for Procedural 3D Generation in Python"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -19,6 +19,9 @@ dependencies = [
|
|
|
19
19
|
Homepage = "https://github.com/princeton-vl/procfunc"
|
|
20
20
|
Repository = "https://github.com/princeton-vl/procfunc"
|
|
21
21
|
|
|
22
|
+
[project.scripts]
|
|
23
|
+
procfunc = "procfunc.cli:cli"
|
|
24
|
+
|
|
22
25
|
[project.optional-dependencies]
|
|
23
26
|
dev = [
|
|
24
27
|
"pytest",
|
|
@@ -29,13 +32,14 @@ dev = [
|
|
|
29
32
|
docs = [
|
|
30
33
|
"sphinx",
|
|
31
34
|
"sphinx-rtd-theme",
|
|
35
|
+
"sphinx-argparse",
|
|
32
36
|
]
|
|
33
37
|
|
|
34
38
|
[tool.setuptools.packages.find]
|
|
35
39
|
where = ["src"]
|
|
36
40
|
|
|
37
41
|
[tool.setuptools.package-data]
|
|
38
|
-
procfunc = ["
|
|
42
|
+
procfunc = ["nodes/manifest.json", "ops/manifest.json"]
|
|
39
43
|
|
|
40
44
|
[tool.pytest.ini_options]
|
|
41
45
|
testpaths = "tests"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# ensure this gets imported first so that mathutils etc is available even if later modules dont import bpy
|
|
3
3
|
import bpy
|
|
4
4
|
|
|
5
|
-
__version__ = "0.30.
|
|
5
|
+
__version__ = "0.30.2"
|
|
6
6
|
|
|
7
7
|
from numpy.random import Generator as RNG
|
|
8
8
|
|
|
@@ -41,6 +41,7 @@ from .types import (
|
|
|
41
41
|
LightObject,
|
|
42
42
|
LightProbeObject,
|
|
43
43
|
MetaObject,
|
|
44
|
+
PointCloudObject,
|
|
44
45
|
Material,
|
|
45
46
|
Texture,
|
|
46
47
|
Collection,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from procfunc.transpiler import main as transpiler_main
|
|
4
|
+
from procfunc.util.teardown import skip_teardown_on_exit
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_parser() -> argparse.ArgumentParser:
|
|
8
|
+
parser = argparse.ArgumentParser(prog="procfunc")
|
|
9
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
10
|
+
|
|
11
|
+
transpile_parser = subparsers.add_parser(
|
|
12
|
+
"transpile", help="Transpile a Blender file to procfunc Python code."
|
|
13
|
+
)
|
|
14
|
+
transpiler_main.add_transpile_arguments(transpile_parser)
|
|
15
|
+
|
|
16
|
+
return parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
parser = get_parser()
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
|
|
23
|
+
if args.command == "transpile":
|
|
24
|
+
transpiler_main.run(args)
|
|
25
|
+
else:
|
|
26
|
+
parser.error(f"Unknown command: {args.command}")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def cli():
|
|
30
|
+
with skip_teardown_on_exit():
|
|
31
|
+
main()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
cli()
|
|
@@ -11,13 +11,13 @@ import numpy as np
|
|
|
11
11
|
|
|
12
12
|
import procfunc as pf
|
|
13
13
|
from procfunc import compute_graph as cg
|
|
14
|
+
from procfunc.codegen import identifiers
|
|
14
15
|
from procfunc.compute_graph.operators_info import (
|
|
15
16
|
FUNCTIONS_TO_OPERATORS,
|
|
16
17
|
OPERATOR_TEMPLATES,
|
|
17
18
|
OperatorType,
|
|
18
19
|
)
|
|
19
20
|
from procfunc.nodes import types as nt
|
|
20
|
-
from procfunc.transpiler import identifiers
|
|
21
21
|
from procfunc.util import pytree
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
@@ -97,7 +97,7 @@ def _repr_value(value: Any) -> str:
|
|
|
97
97
|
elif isinstance(value, np.dtype):
|
|
98
98
|
return f"np.dtype('{value}')"
|
|
99
99
|
elif isinstance(value, (pf.Color, pf.Vector, pf.Euler, pf.Quaternion, pf.Matrix)):
|
|
100
|
-
x = tuple(round(x,
|
|
100
|
+
x = tuple(round(x, 8) for x in value)
|
|
101
101
|
return f"pf.{value.__class__.__name__}({x})"
|
|
102
102
|
elif isinstance(value, enum.Enum):
|
|
103
103
|
return f"{type(value).__name__}.{value.name}"
|
|
@@ -111,6 +111,11 @@ def _repr_value(value: Any) -> str:
|
|
|
111
111
|
return f"{type(value).__name__}({args_str})"
|
|
112
112
|
elif isinstance(value, list):
|
|
113
113
|
return f"[{', '.join([_repr_value(x) for x in value])}]"
|
|
114
|
+
elif isinstance(value, tuple):
|
|
115
|
+
inner = ", ".join(_repr_value(x) for x in value)
|
|
116
|
+
return f"({inner},)" if len(value) == 1 else f"({inner})"
|
|
117
|
+
elif isinstance(value, float) and not isinstance(value, bool):
|
|
118
|
+
return repr(round(value, 8))
|
|
114
119
|
else:
|
|
115
120
|
return repr(value)
|
|
116
121
|
|
|
@@ -389,7 +394,9 @@ def _codegen_for_outputs(
|
|
|
389
394
|
scope_expressions: dict[int, str | list[str]],
|
|
390
395
|
) -> tuple[str | None, list[str], list[str]]:
|
|
391
396
|
if len(graph.outputs) == 0:
|
|
392
|
-
return
|
|
397
|
+
# Sink graphs (no return values) still need a body statement so the
|
|
398
|
+
# generated function parses; emit `pass` when nothing else fills it.
|
|
399
|
+
return None, [], ["pass"]
|
|
393
400
|
if len(graph.outputs) == 1:
|
|
394
401
|
single_output = next(graph.outputs.values())
|
|
395
402
|
vt = single_output.metadata.get("known_value_type", None)
|
|
@@ -720,7 +727,7 @@ def default_func_resolution_map(
|
|
|
720
727
|
skip_funcs: set | None = None,
|
|
721
728
|
) -> tuple[dict[Any, str | OperatorType], list[str]]:
|
|
722
729
|
func_resolution = {}
|
|
723
|
-
import_lines =
|
|
730
|
+
import_lines = {"import procfunc as pf"}
|
|
724
731
|
|
|
725
732
|
for graph in cg.traverse_nested_graphs(toplevel_graph):
|
|
726
733
|
assert isinstance(graph, cg.ComputeGraph), graph
|
|
@@ -56,13 +56,6 @@ class FunctionCallNode(Node):
|
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class MethodCallNode(Node):
|
|
59
|
-
"""
|
|
60
|
-
represents an {args[0]}.{method_name}(*args[1:], **kwargs) call
|
|
61
|
-
|
|
62
|
-
- the node to be used as `self` is the first arg, since it is a dynamic value
|
|
63
|
-
- the method name is assumed to be const
|
|
64
|
-
"""
|
|
65
|
-
|
|
66
59
|
def __init__(
|
|
67
60
|
self,
|
|
68
61
|
callee: Node,
|
|
@@ -161,7 +154,7 @@ def normalize_args_to_kwargs(
|
|
|
161
154
|
"""
|
|
162
155
|
Try to fully populate kwargs, by moving over positional args & filling in defaults
|
|
163
156
|
|
|
164
|
-
Some args may not be able to be converted to kwargs, e.g.
|
|
157
|
+
Some args may not be able to be converted to kwargs, e.g. ``*args`` have no names that work
|
|
165
158
|
|
|
166
159
|
Args:
|
|
167
160
|
func: The function whose signature we should respect
|
|
@@ -171,7 +164,7 @@ def normalize_args_to_kwargs(
|
|
|
171
164
|
Returns:
|
|
172
165
|
A tuple of (args, kwargs) where args is a tuple of positional arguments and kwargs is a dictionary of keyword arguments.
|
|
173
166
|
|
|
174
|
-
GUARANTEE: func(*returned_args, **returned_kwargs) == func(*args, **kwargs) and does not crash
|
|
167
|
+
GUARANTEE: ``func(*returned_args, **returned_kwargs) == func(*args, **kwargs)`` and does not crash
|
|
175
168
|
"""
|
|
176
169
|
|
|
177
170
|
sig = inspect.signature(func)
|
|
@@ -3,15 +3,17 @@ from pandas import read_json as _read_json
|
|
|
3
3
|
from procfunc.tracer import autowrap_module as _autowrap
|
|
4
4
|
from procfunc.util.manifest import module_path
|
|
5
5
|
|
|
6
|
-
from . import compositor, func, geo, math, shader
|
|
6
|
+
from . import color, compositor, func, geo, math, shader, texture
|
|
7
7
|
from .bpy_node_info import NodeDataType, NodeGroupType, SocketType
|
|
8
8
|
|
|
9
9
|
# ruff: noqa: E402
|
|
10
|
+
_autowrap(color, allow_exec=False)
|
|
10
11
|
_autowrap(compositor, allow_exec=False)
|
|
11
12
|
_autowrap(func, allow_exec=False)
|
|
12
13
|
_autowrap(geo, allow_exec=False)
|
|
13
14
|
_autowrap(math, allow_exec=False)
|
|
14
15
|
_autowrap(shader, allow_exec=False)
|
|
16
|
+
_autowrap(texture, allow_exec=False)
|
|
15
17
|
|
|
16
18
|
from .execute.execute import (
|
|
17
19
|
as_nodegroup,
|
|
@@ -38,11 +40,13 @@ NODES_MANIFEST = _read_json(NODES_MANIFEST_PATH)
|
|
|
38
40
|
|
|
39
41
|
__all__ = [
|
|
40
42
|
# Node category submodules
|
|
43
|
+
"color",
|
|
41
44
|
"compositor",
|
|
42
45
|
"func",
|
|
43
46
|
"geo",
|
|
44
47
|
"math",
|
|
45
48
|
"shader",
|
|
49
|
+
"texture",
|
|
46
50
|
# Core types
|
|
47
51
|
"ProcNode",
|
|
48
52
|
"Shader",
|
|
@@ -24,6 +24,11 @@ class ContextualNode(Enum):
|
|
|
24
24
|
GROUP = "ContextualGroup"
|
|
25
25
|
MIX_RGB = "ContextualMixRGB"
|
|
26
26
|
MATH = "ContextualMath"
|
|
27
|
+
COLOR_RAMP = "ContextualColorRamp"
|
|
28
|
+
VECTOR_CURVE = "ContextualVectorCurve"
|
|
29
|
+
COMBINE_XYZ = "ContextualCombineXYZ"
|
|
30
|
+
MAP_RANGE = "ContextualMapRange"
|
|
31
|
+
HUE_SATURATION = "ContextualHueSaturation"
|
|
27
32
|
|
|
28
33
|
@classmethod
|
|
29
34
|
def parse_name(cls, from_name: str) -> Self | None:
|
|
@@ -39,6 +44,7 @@ class NodeContextResolution:
|
|
|
39
44
|
node_group_type: NodeGroupType
|
|
40
45
|
node_type: str
|
|
41
46
|
input_keys_map: dict[str, tuple[str, int] | str | None] | None
|
|
47
|
+
output_keys_map: dict[str, str] | None = None
|
|
42
48
|
|
|
43
49
|
|
|
44
50
|
# Mapping to map unified version of nodes to context-specific blender versions
|
|
@@ -64,6 +70,12 @@ CONTEXTUAL_NODE_MAPPING = [
|
|
|
64
70
|
node_type="FunctionNodeCombineColor",
|
|
65
71
|
input_keys_map=None,
|
|
66
72
|
),
|
|
73
|
+
NodeContextResolution(
|
|
74
|
+
contextual_node=ContextualNode.COMBINE_COLOR,
|
|
75
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
76
|
+
node_type="CompositorNodeCombineColor",
|
|
77
|
+
input_keys_map=None,
|
|
78
|
+
),
|
|
67
79
|
NodeContextResolution(
|
|
68
80
|
contextual_node=ContextualNode.SEPARATE_COLOR,
|
|
69
81
|
node_group_type=NodeGroupType.SHADER,
|
|
@@ -130,6 +142,12 @@ CONTEXTUAL_NODE_MAPPING = [
|
|
|
130
142
|
node_type="ShaderNodeMath",
|
|
131
143
|
input_keys_map=None,
|
|
132
144
|
),
|
|
145
|
+
NodeContextResolution(
|
|
146
|
+
contextual_node=ContextualNode.MATH,
|
|
147
|
+
node_group_type=NodeGroupType.GEOMETRY,
|
|
148
|
+
node_type="ShaderNodeMath",
|
|
149
|
+
input_keys_map=None,
|
|
150
|
+
),
|
|
133
151
|
NodeContextResolution(
|
|
134
152
|
contextual_node=ContextualNode.MATH,
|
|
135
153
|
node_group_type=NodeGroupType.COMPOSITOR,
|
|
@@ -142,12 +160,104 @@ CONTEXTUAL_NODE_MAPPING = [
|
|
|
142
160
|
node_type="TextureNodeMath",
|
|
143
161
|
input_keys_map=None,
|
|
144
162
|
),
|
|
163
|
+
NodeContextResolution(
|
|
164
|
+
contextual_node=ContextualNode.COLOR_RAMP,
|
|
165
|
+
node_group_type=NodeGroupType.SHADER,
|
|
166
|
+
node_type="ShaderNodeValToRGB",
|
|
167
|
+
input_keys_map=None,
|
|
168
|
+
),
|
|
169
|
+
NodeContextResolution(
|
|
170
|
+
contextual_node=ContextualNode.COLOR_RAMP,
|
|
171
|
+
node_group_type=NodeGroupType.GEOMETRY,
|
|
172
|
+
node_type="ShaderNodeValToRGB",
|
|
173
|
+
input_keys_map=None,
|
|
174
|
+
),
|
|
175
|
+
NodeContextResolution(
|
|
176
|
+
contextual_node=ContextualNode.COLOR_RAMP,
|
|
177
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
178
|
+
node_type="CompositorNodeValToRGB",
|
|
179
|
+
input_keys_map=None,
|
|
180
|
+
output_keys_map={"Color": "Image"},
|
|
181
|
+
),
|
|
182
|
+
NodeContextResolution(
|
|
183
|
+
contextual_node=ContextualNode.VECTOR_CURVE,
|
|
184
|
+
node_group_type=NodeGroupType.SHADER,
|
|
185
|
+
node_type="ShaderNodeVectorCurve",
|
|
186
|
+
input_keys_map=None,
|
|
187
|
+
),
|
|
188
|
+
NodeContextResolution(
|
|
189
|
+
contextual_node=ContextualNode.VECTOR_CURVE,
|
|
190
|
+
node_group_type=NodeGroupType.GEOMETRY,
|
|
191
|
+
node_type="ShaderNodeVectorCurve",
|
|
192
|
+
input_keys_map=None,
|
|
193
|
+
),
|
|
194
|
+
NodeContextResolution(
|
|
195
|
+
contextual_node=ContextualNode.VECTOR_CURVE,
|
|
196
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
197
|
+
# CompositorNodeCurveVec has no Fac input; the wrapper's `fac` arg is dropped
|
|
198
|
+
# silently in compositor context. Honoring fac would require synthesizing an
|
|
199
|
+
# extra mix node.
|
|
200
|
+
node_type="CompositorNodeCurveVec",
|
|
201
|
+
input_keys_map={"Fac": None},
|
|
202
|
+
),
|
|
203
|
+
NodeContextResolution(
|
|
204
|
+
contextual_node=ContextualNode.COMBINE_XYZ,
|
|
205
|
+
node_group_type=NodeGroupType.SHADER,
|
|
206
|
+
node_type="ShaderNodeCombineXYZ",
|
|
207
|
+
input_keys_map=None,
|
|
208
|
+
),
|
|
209
|
+
NodeContextResolution(
|
|
210
|
+
contextual_node=ContextualNode.COMBINE_XYZ,
|
|
211
|
+
node_group_type=NodeGroupType.GEOMETRY,
|
|
212
|
+
node_type="ShaderNodeCombineXYZ",
|
|
213
|
+
input_keys_map=None,
|
|
214
|
+
),
|
|
215
|
+
NodeContextResolution(
|
|
216
|
+
contextual_node=ContextualNode.COMBINE_XYZ,
|
|
217
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
218
|
+
node_type="CompositorNodeCombineXYZ",
|
|
219
|
+
input_keys_map=None,
|
|
220
|
+
),
|
|
221
|
+
NodeContextResolution(
|
|
222
|
+
contextual_node=ContextualNode.MAP_RANGE,
|
|
223
|
+
node_group_type=NodeGroupType.SHADER,
|
|
224
|
+
node_type="ShaderNodeMapRange",
|
|
225
|
+
input_keys_map=None,
|
|
226
|
+
),
|
|
227
|
+
NodeContextResolution(
|
|
228
|
+
contextual_node=ContextualNode.MAP_RANGE,
|
|
229
|
+
node_group_type=NodeGroupType.GEOMETRY,
|
|
230
|
+
node_type="ShaderNodeMapRange",
|
|
231
|
+
input_keys_map=None,
|
|
232
|
+
),
|
|
233
|
+
NodeContextResolution(
|
|
234
|
+
contextual_node=ContextualNode.MAP_RANGE,
|
|
235
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
236
|
+
# CompositorNodeMapRange exposes only float Value and use_clamp; it has
|
|
237
|
+
# no interpolation_type and no vector data_type. The wrapper omits
|
|
238
|
+
# those attrs when at default, so setattr only fails (with its own
|
|
239
|
+
# "no attribute" error) when a user actually requested a non-default.
|
|
240
|
+
node_type="CompositorNodeMapRange",
|
|
241
|
+
input_keys_map={"clamp": "use_clamp"},
|
|
242
|
+
),
|
|
243
|
+
NodeContextResolution(
|
|
244
|
+
contextual_node=ContextualNode.HUE_SATURATION,
|
|
245
|
+
node_group_type=NodeGroupType.SHADER,
|
|
246
|
+
node_type="ShaderNodeHueSaturation",
|
|
247
|
+
input_keys_map=None,
|
|
248
|
+
),
|
|
249
|
+
NodeContextResolution(
|
|
250
|
+
contextual_node=ContextualNode.HUE_SATURATION,
|
|
251
|
+
node_group_type=NodeGroupType.COMPOSITOR,
|
|
252
|
+
node_type="CompositorNodeHueSat",
|
|
253
|
+
input_keys_map={"Color": "Image"},
|
|
254
|
+
),
|
|
145
255
|
]
|
|
146
256
|
|
|
147
257
|
|
|
148
258
|
def resolve_contextual_node(
|
|
149
259
|
node: list[NodeContextResolution], group: NodeGroupType
|
|
150
|
-
) ->
|
|
260
|
+
) -> NodeContextResolution:
|
|
151
261
|
item = next(
|
|
152
262
|
(
|
|
153
263
|
item
|
|
@@ -160,7 +270,7 @@ def resolve_contextual_node(
|
|
|
160
270
|
if item is None:
|
|
161
271
|
raise ValueError(f"No contextual node found for {node} in {group}")
|
|
162
272
|
|
|
163
|
-
return item
|
|
273
|
+
return item
|
|
164
274
|
|
|
165
275
|
|
|
166
276
|
def raise_shader_normal_error(node_func_name: str, logger: logging.Logger):
|
|
@@ -58,6 +58,8 @@ class SocketType(Enum):
|
|
|
58
58
|
COLLECTION = "NodeSocketCollection"
|
|
59
59
|
TEXTURE = "NodeSocketTexture"
|
|
60
60
|
MATERIAL = "NodeSocketMaterial"
|
|
61
|
+
MATRIX = "NodeSocketMatrix"
|
|
62
|
+
IMAGE = "NodeSocketImage"
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
class SocketDType(Enum):
|
|
@@ -150,6 +152,10 @@ SOCKET_TYPE_TO_PYTHON_TYPE = {
|
|
|
150
152
|
SocketType.COLLECTION: pt.Collection,
|
|
151
153
|
SocketType.MATERIAL: pt.Material,
|
|
152
154
|
SocketType.SHADER: nt.Shader,
|
|
155
|
+
SocketType.OBJECT: pt.Object,
|
|
156
|
+
SocketType.TEXTURE: pt.Texture,
|
|
157
|
+
SocketType.MATRIX: pt.Matrix,
|
|
158
|
+
SocketType.IMAGE: pt.Image,
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
# Socket types that can be implicitly converted between each other
|
|
@@ -263,6 +269,7 @@ SPECIAL_CASE_ATTR_NAMES = set(
|
|
|
263
269
|
"interface",
|
|
264
270
|
"node_tree",
|
|
265
271
|
"tag_need_exec",
|
|
272
|
+
"index_switch_items",
|
|
266
273
|
]
|
|
267
274
|
)
|
|
268
275
|
|