node_to_json 0.1.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.
- node_to_json/__init__.py +53 -0
- node_to_json/asset_funcs.py +74 -0
- node_to_json/func_util.py +90 -0
- node_to_json/json_io.py +31 -0
- node_to_json/node_getters.py +471 -0
- node_to_json/node_registry.py +56 -0
- node_to_json/node_setters.py +433 -0
- node_to_json/py.typed +0 -0
- node_to_json/setter_funcs.py +452 -0
- node_to_json/type_util.py +10 -0
- node_to_json-0.1.1.dist-info/METADATA +13 -0
- node_to_json-0.1.1.dist-info/RECORD +13 -0
- node_to_json-0.1.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import bpy
|
|
2
|
+
from .asset_funcs import get_asset_nodes, asset_node_group
|
|
3
|
+
from .setter_funcs import set_node_from_data
|
|
4
|
+
from .type_util import BNode, BGroup, PYDict
|
|
5
|
+
from .func_util import convert_default_value
|
|
6
|
+
from .node_registry import register_ng_setter
|
|
7
|
+
from typing import Generator
|
|
8
|
+
from itertools import tee, repeat
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
socket_attr = [
|
|
12
|
+
'description',
|
|
13
|
+
'enabled',
|
|
14
|
+
'hide',
|
|
15
|
+
'hide_value',
|
|
16
|
+
'name',
|
|
17
|
+
'pin_gizmo',
|
|
18
|
+
'show_expanded',
|
|
19
|
+
'type',
|
|
20
|
+
'is_linked',
|
|
21
|
+
'default_value',
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
tree_exclude = [
|
|
25
|
+
'name',
|
|
26
|
+
'description',
|
|
27
|
+
'in_out',
|
|
28
|
+
'socket_type',
|
|
29
|
+
'default_closed',
|
|
30
|
+
'index',
|
|
31
|
+
'position',
|
|
32
|
+
'parent',
|
|
33
|
+
'identifier',
|
|
34
|
+
'is_multi_input',
|
|
35
|
+
'item_type',
|
|
36
|
+
'persistent_uid',
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
########################## NODE ###########################
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def set_socket_attr(node: BNode, attr: PYDict, set_enum: bool=False) -> None:
|
|
44
|
+
def _set_sock(fil):
|
|
45
|
+
for sock, a in fil:
|
|
46
|
+
try:
|
|
47
|
+
setattr(sock, 'default_value', convert_default_value(sock, a['default_value']))
|
|
48
|
+
except Exception as e:
|
|
49
|
+
continue
|
|
50
|
+
condition = lambda i: i[1]['type'] not in ['CUSTOM'] and (True if set_enum else i[0].type not in ['MENU']) and not i[1]['is_linked'] and 'default_value' in i[1].keys()
|
|
51
|
+
inputs = getattr(node, 'inputs', None)
|
|
52
|
+
if inputs:
|
|
53
|
+
ifil = filter(condition, zip(inputs[:], attr['inputs']))
|
|
54
|
+
_set_sock(ifil)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def set_parent(node: BNode, attr: PYDict) -> None:
|
|
58
|
+
if hasattr(node, 'parent'):
|
|
59
|
+
if 'parent' in attr.keys():
|
|
60
|
+
if attr['parent'] not in [None, '']:
|
|
61
|
+
try:
|
|
62
|
+
setattr(node, 'parent', node.id_data.nodes[attr['parent']])
|
|
63
|
+
except Exception as e:
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def set_hide(node: BNode, attr: PYDict) -> None:
|
|
68
|
+
if 'inputs' in attr.keys():
|
|
69
|
+
if attr['inputs'] not in [None, []]:
|
|
70
|
+
try:
|
|
71
|
+
node.inputs.foreach_set('hide', list(i['hide'] for i in attr['inputs']))
|
|
72
|
+
except Exception as e:
|
|
73
|
+
pass
|
|
74
|
+
if 'outputs' in attr.keys():
|
|
75
|
+
if attr['outputs'] not in [None, []]:
|
|
76
|
+
try:
|
|
77
|
+
node.outputs.foreach_set('hide', list(i['hide'] for i in attr['outputs']))
|
|
78
|
+
except Exception as e:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def process_node(node: BNode, data: PYDict, group_dict: dict[str, BGroup] | dict[None], parent: bool=True, set_enum: bool=False) -> None:
|
|
83
|
+
"""Set node attributes from data.
|
|
84
|
+
|
|
85
|
+
:param node: Node to set the data to.
|
|
86
|
+
:type node: Node
|
|
87
|
+
:param data: Data used to set the node attributes.
|
|
88
|
+
:type data: dict[str, Any]
|
|
89
|
+
:param group_dict: Dict containing the node group objects.
|
|
90
|
+
:type group_dict: dict[str, Node Group]
|
|
91
|
+
:param parent: Set parent node if available.
|
|
92
|
+
:type parent: bool
|
|
93
|
+
:param set_enum: Dict containing the node group enum sockets.
|
|
94
|
+
:type set_enum: bool"""
|
|
95
|
+
try:
|
|
96
|
+
set_node_from_data(node, data, group_dict)
|
|
97
|
+
set_socket_attr(node, data, set_enum=set_enum)
|
|
98
|
+
if node.bl_idname not in ['NodeReroute']:
|
|
99
|
+
set_hide(node, data)
|
|
100
|
+
if parent:
|
|
101
|
+
set_parent(node, data)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def set_nodes_from_data(data_dict: PYDict, node_dict: dict[str, BNode], group_dict: dict[str, BGroup]) -> None:
|
|
107
|
+
asset_nodes = set(get_asset_nodes())
|
|
108
|
+
for group, nodes in node_dict.items():
|
|
109
|
+
if group.split(".")[0] not in asset_nodes:
|
|
110
|
+
for _node, node in nodes.items():
|
|
111
|
+
process_node(node, data_dict[group]['nodes'][_node], group_dict)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
####################### NODE GROUP ########################
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def create_node_groups_from_data(data: PYDict, group_type: str='GeometryNodeTree') -> Generator[tuple[str, BGroup], None, None]:
|
|
118
|
+
asset_nodes = set(get_asset_nodes())
|
|
119
|
+
return ((group, asset_node_group(group.split(".")[0]) if group.split(".")[0] in asset_nodes else bpy.data.node_groups.new(group, group_type)) for group in reversed(data.keys()))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def create_node_tree_nodes(node_tree: BGroup, data_nodes: PYDict) -> Generator[tuple[str, BNode], None, None]:
|
|
123
|
+
for node in data_nodes:
|
|
124
|
+
_node = node_tree.nodes.new(data_nodes[node]['bl_idname'])
|
|
125
|
+
_node.name = data_nodes[node]['name']
|
|
126
|
+
yield node, _node
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def node_map(data: PYDict, groups: dict[str, BNode]) -> Generator[tuple[str, dict[str, BNode]], None, None]:
|
|
130
|
+
for group in groups:
|
|
131
|
+
if group[1] not in [None, ''] and data[group[0]]['nodes'] not in [None, '']:
|
|
132
|
+
yield group[0], dict(create_node_tree_nodes(group[1], data[group[0]]['nodes']))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def node_group_map(data: PYDict, group_type: str='GeometryNodeTree') -> tuple[str, Generator[tuple[str, dict[str, BNode]], None, None]]:
|
|
136
|
+
groups, _groups = tee(create_node_groups_from_data(data, group_type=group_type), 2)
|
|
137
|
+
return groups, node_map(data, _groups)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def set_interface(data: PYDict, node_tree: BGroup) -> None:
|
|
141
|
+
"""Set sockets of node group from data.
|
|
142
|
+
|
|
143
|
+
:param data: Data to set the sockets.
|
|
144
|
+
:type data: dict[str, Any]
|
|
145
|
+
:param node_tree: Node group to set data to.
|
|
146
|
+
:type node_tree: Node Group"""
|
|
147
|
+
global tree_exclude
|
|
148
|
+
if 'interface' in data.keys() and data['interface'] != None and hasattr(node_tree, 'interface'):
|
|
149
|
+
for item in data['interface']:
|
|
150
|
+
for attr in item.keys():
|
|
151
|
+
if attr not in tree_exclude:
|
|
152
|
+
it = node_tree.interface.items_tree[data['interface']['index']]
|
|
153
|
+
if hasattr(it, attr) and item[attr] not in [None, '', []]:
|
|
154
|
+
try:
|
|
155
|
+
setattr(it, attr, item[attr])
|
|
156
|
+
except Exception:
|
|
157
|
+
try:
|
|
158
|
+
gi = getattr(it, attr, None)
|
|
159
|
+
if isinstance(gi, bpy.types.bpy_prop_array):
|
|
160
|
+
ct = len(gi)
|
|
161
|
+
_ct = len(item[attr])
|
|
162
|
+
count = ct if _ct > ct else _ct
|
|
163
|
+
val = list(repeat(0.0, ct))
|
|
164
|
+
for i in range(count):
|
|
165
|
+
val[i] = item[attr][i]
|
|
166
|
+
setattr(it, attr, val)
|
|
167
|
+
except Exception:
|
|
168
|
+
continue
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def set_node_groups_from_data(data: PYDict, group_type: str='GeometryNodeTree') -> tuple[dict[str, BGroup], PYDict, PYDict, dict[str, BNode]]:
|
|
173
|
+
"""Set node tree attributes from build data.
|
|
174
|
+
|
|
175
|
+
:param data: Node group build data.
|
|
176
|
+
:type data: dict[str, Any]
|
|
177
|
+
:param group_type: String indicating the bpy type of the node group.
|
|
178
|
+
:type group_type: str
|
|
179
|
+
:return: Tuple containing dictionaries for node group data, enum socket data, data to build node group, and node data.
|
|
180
|
+
:rtype: tuple[dict[str, node tree], dict[node_group.interface.items_tree, item], dict[str, Any], dict[str, node]]"""
|
|
181
|
+
global tree_exclude
|
|
182
|
+
group_dict, node_dict = node_group_map(data, group_type=group_type)
|
|
183
|
+
group_dict, group_dict_, _group_dict = tee(group_dict, 3)
|
|
184
|
+
[[setattr(group[1], a, data[group[0]][a]) for a in data[group[0]] if hasattr(group[1], a) and a not in ['interface', 'links', 'nodes', 'node_tree', 'bl_idname']] for group in group_dict]
|
|
185
|
+
def _set_interface(_group):
|
|
186
|
+
group, node_tree = _group
|
|
187
|
+
enums = []
|
|
188
|
+
if 'interface' in data[group].keys() and data[group]['interface'] != None and hasattr(node_tree, 'interface'):
|
|
189
|
+
for idx, item in enumerate(data[group]['interface']):
|
|
190
|
+
if item['item_type'] == 'SOCKET':
|
|
191
|
+
it = node_tree.interface.new_socket(item['name'], description=item['description'], in_out=item['in_out'], socket_type=item['socket_type'])
|
|
192
|
+
if item['socket_type'] == 'NodeSocketMenu' and (hasattr(it, 'default_value') and item['default_value'] not in [None, '']):
|
|
193
|
+
enums.append([it, idx])
|
|
194
|
+
elif item['item_type'] == 'PANEL':
|
|
195
|
+
it = node_tree.interface.new_panel(item['name'], description=item['description'], default_closed=item['default_closed'])
|
|
196
|
+
else:
|
|
197
|
+
it = None
|
|
198
|
+
for attr in item.keys():
|
|
199
|
+
if attr not in tree_exclude:
|
|
200
|
+
if it != None:
|
|
201
|
+
try:
|
|
202
|
+
if hasattr(it, attr) and item[attr] not in [None, '', []]:
|
|
203
|
+
if attr == 'default_value' and data[group]['interface'][idx]['socket_type'] == 'NodeSocketMenu':
|
|
204
|
+
continue
|
|
205
|
+
else:
|
|
206
|
+
setattr(it, attr, item[attr])
|
|
207
|
+
except Exception:
|
|
208
|
+
try:
|
|
209
|
+
gi = getattr(it, attr, None)
|
|
210
|
+
if isinstance(gi, bpy.types.bpy_prop_array):
|
|
211
|
+
ct = len(gi)
|
|
212
|
+
_ct = len(item[attr])
|
|
213
|
+
count = ct if _ct > ct else _ct
|
|
214
|
+
val = list(repeat(0.0, ct))
|
|
215
|
+
for i in range(count):
|
|
216
|
+
val[i] = item[attr][i]
|
|
217
|
+
setattr(it, attr, val)
|
|
218
|
+
except Exception:
|
|
219
|
+
continue
|
|
220
|
+
data[group]['interface'][idx]['item'] = it
|
|
221
|
+
return group, enums
|
|
222
|
+
enum_dict = dict(_set_interface(group) for group in group_dict_)
|
|
223
|
+
return dict(_group_dict), enum_dict, data, dict(node_dict)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _new_link(link: bpy.types.NodeLink, node_tree: BGroup) -> None:
|
|
227
|
+
from_node = link[0]['node']
|
|
228
|
+
to_node = link[1]['node']
|
|
229
|
+
from_socket = link[0]['socket']
|
|
230
|
+
to_socket = link[1]['socket']
|
|
231
|
+
output = node_tree.nodes[from_node]
|
|
232
|
+
input = node_tree.nodes[to_node]
|
|
233
|
+
node_tree.links.new(output.outputs[from_socket], input.inputs[to_socket], verify_limits=True, handle_dynamic_sockets=True)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def set_node_group_links(data: PYDict, group_dict: dict[str, BGroup]) -> None:
|
|
237
|
+
asset_nodes = set(get_asset_nodes())
|
|
238
|
+
for tree in reversed(data.keys()):
|
|
239
|
+
if tree.split(".")[0] not in asset_nodes:
|
|
240
|
+
node_tree = group_dict[tree]
|
|
241
|
+
if not isinstance(node_tree, type(None)) and data[tree]['links'] != None:
|
|
242
|
+
for link in data[tree]['links']:
|
|
243
|
+
try:
|
|
244
|
+
_new_link(link, node_tree)
|
|
245
|
+
except IndexError:
|
|
246
|
+
continue
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def set_node_groups_enums(data: PYDict, enum_dict: PYDict) -> None:
|
|
250
|
+
for group in enum_dict:
|
|
251
|
+
for item in enum_dict[group]:
|
|
252
|
+
try:
|
|
253
|
+
item[0].default_value = data[group]['interface'][item[1]]['default_value']
|
|
254
|
+
except Exception:
|
|
255
|
+
continue
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def set_node_groups_interface_parents(data: PYDict, group_dict: dict[str, BGroup]) -> None:
|
|
259
|
+
asset_nodes = set(get_asset_nodes())
|
|
260
|
+
for group in reversed(data.keys()):
|
|
261
|
+
if group.split(".")[0] not in asset_nodes:
|
|
262
|
+
node_tree = group_dict[group]
|
|
263
|
+
_interface = data[group]['interface']
|
|
264
|
+
if _interface:
|
|
265
|
+
for i in range(len(_interface)):
|
|
266
|
+
try:
|
|
267
|
+
parent, pid = _interface[i]['parent']
|
|
268
|
+
position = _interface[i]['index']
|
|
269
|
+
item = _interface[i]['item']
|
|
270
|
+
if parent != "":
|
|
271
|
+
parent_ = next((p['item'] for p in (_ for _ in _interface if _['item_type'] == 'PANEL') if [parent, pid] == [p['name'], p['persistent_uid']]))
|
|
272
|
+
node_tree.interface.move_to_parent(item, parent_, position)
|
|
273
|
+
except Exception:
|
|
274
|
+
continue
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@register_ng_setter('GeometryNodeTree')
|
|
278
|
+
def create_node_group_from_data(data: PYDict, group_type: str='GeometryNodeTree') -> BGroup:
|
|
279
|
+
"""Create a node group from build data.
|
|
280
|
+
|
|
281
|
+
:param data: Dictionary containing data to build node grouo.
|
|
282
|
+
:type data: dict[str, Any]
|
|
283
|
+
:param group_type: String indicating the bpy type of the node group.
|
|
284
|
+
:type group_type: str
|
|
285
|
+
:return: NodeGroup.
|
|
286
|
+
:rtype: NodeGroup"""
|
|
287
|
+
group_dict, enum_dict, data, node_dict = set_node_groups_from_data(data, group_type=group_type)
|
|
288
|
+
set_nodes_from_data(data, node_dict, group_dict)
|
|
289
|
+
set_node_group_links(data, group_dict)
|
|
290
|
+
set_node_groups_enums(data, enum_dict)
|
|
291
|
+
set_node_groups_interface_parents(data, group_dict)
|
|
292
|
+
node_group = next(g for g in reversed(group_dict.values()))
|
|
293
|
+
return node_group
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def add_node_group(ob: bpy.types.Object, name: str, data: PYDict) -> bpy.types.Modifier:
|
|
297
|
+
"""Create Geometry Node modifier and node group.
|
|
298
|
+
|
|
299
|
+
:param ob: Object to add modifier to.
|
|
300
|
+
:type ob: Object
|
|
301
|
+
:param name: Modifier name.
|
|
302
|
+
:type name: str
|
|
303
|
+
:param data: Data to build node group to assign to the modifier.
|
|
304
|
+
:type data: dict[str, Any]
|
|
305
|
+
:return: Object modifier.
|
|
306
|
+
:rtype: Modifier"""
|
|
307
|
+
modifier = ob.modifiers.new(name, 'NODES')
|
|
308
|
+
node_group = create_node_group_from_data(data, group_type='GeometryNodeTree')
|
|
309
|
+
modifier.node_group = node_group
|
|
310
|
+
return modifier
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
######################## MATERIAL #########################
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@register_ng_setter('ShaderNodeTree')
|
|
317
|
+
def create_shader_group_from_data(data: PYDict, group_type: str='ShaderNodeTree', return_group_dict: bool=False) -> dict[str, BGroup] | BGroup:
|
|
318
|
+
"""Create Shader Node node group.
|
|
319
|
+
|
|
320
|
+
:param data: Data dict to build shader node group.
|
|
321
|
+
:type data: dict[str, Any]
|
|
322
|
+
:param group_type: String indicating the bpy type of the node group.
|
|
323
|
+
:type group_type: str
|
|
324
|
+
:param return_group_dict: Choose to return the group_dict or the node group.
|
|
325
|
+
:type return_group_dict: bool
|
|
326
|
+
:return: Return a group_dict or node_group.
|
|
327
|
+
:rtype: dict[str, Node Group] | Node Group"""
|
|
328
|
+
group_dict, enum_dict, data, node_dict = set_node_groups_from_data(data, group_type=group_type)
|
|
329
|
+
set_nodes_from_data(data, node_dict, group_dict)
|
|
330
|
+
set_node_group_links(data, group_dict)
|
|
331
|
+
set_node_groups_enums(data, enum_dict)
|
|
332
|
+
set_node_groups_interface_parents(data, group_dict)
|
|
333
|
+
if return_group_dict:
|
|
334
|
+
return group_dict
|
|
335
|
+
node_group = next(g for g in reversed(group_dict.values()))
|
|
336
|
+
return node_group
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def set_shader_from_data(data_dict: PYDict, node_dict: dict[str, BNode], group_dict: dict[str, BGroup]) -> None:
|
|
340
|
+
for _node, node in node_dict.items():
|
|
341
|
+
process_node(node, data_dict[_node], group_dict, set_enum=True)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def create_material(data: PYDict) -> bpy.types.Material:
|
|
345
|
+
"""Create material and Shader Node node group.
|
|
346
|
+
|
|
347
|
+
:param data: Data dict to build material.
|
|
348
|
+
:type data: dict[str, Any]
|
|
349
|
+
:return: Material.
|
|
350
|
+
:rtype: Material"""
|
|
351
|
+
global tree_exclude
|
|
352
|
+
mat_name = list(data.keys())[0]
|
|
353
|
+
material = bpy.data.materials.new(mat_name)
|
|
354
|
+
for a in data[mat_name]:
|
|
355
|
+
if a not in ['node_tree'] and hasattr(material, a):
|
|
356
|
+
setattr(material, a, data[mat_name][a])
|
|
357
|
+
node_tree = getattr(material, 'node_tree', None)
|
|
358
|
+
if node_tree:
|
|
359
|
+
node_tree.nodes.clear()
|
|
360
|
+
mat_data = data[mat_name]['node_tree']
|
|
361
|
+
group_data = mat_data['node_groups']
|
|
362
|
+
nodes_data = mat_data['nodes']
|
|
363
|
+
link_data = mat_data['links']
|
|
364
|
+
group_dict = create_shader_group_from_data(group_data, group_type='ShaderNodeTree', return_group_dict=True)
|
|
365
|
+
nodes_dict = dict(create_node_tree_nodes(node_tree, nodes_data))
|
|
366
|
+
set_shader_from_data(nodes_data, nodes_dict, group_dict)
|
|
367
|
+
for link in link_data:
|
|
368
|
+
_new_link(link, node_tree)
|
|
369
|
+
return material
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def add_material_to_ob(ob: bpy.types.Object, data: PYDict) -> bpy.types.Material:
|
|
373
|
+
"""Create material from data and add to object material slot.
|
|
374
|
+
|
|
375
|
+
:param ob: Object to add material to.
|
|
376
|
+
:type ob: Object
|
|
377
|
+
:param data: Data dict to build material.
|
|
378
|
+
:type data: dict[str, Any]
|
|
379
|
+
:return: Material.
|
|
380
|
+
:rtype: Material"""
|
|
381
|
+
materials = ob.data.materials
|
|
382
|
+
material = create_material(data)
|
|
383
|
+
materials.append(material)
|
|
384
|
+
return material
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
####################### COMPOSITOR ########################
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
@register_ng_setter('CompositorNodeTree')
|
|
391
|
+
def create_comp_group(data: PYDict) -> BGroup:
|
|
392
|
+
"""Create compositor node group.
|
|
393
|
+
|
|
394
|
+
:param data: Data dict to build compositor node group.
|
|
395
|
+
:type data: dict[str, Any]
|
|
396
|
+
:return: Compositor NodeGroup.
|
|
397
|
+
:rtype: NodeGroup"""
|
|
398
|
+
try:
|
|
399
|
+
node_group = create_node_group_from_data(data, group_type='CompositorNodeTree')
|
|
400
|
+
return node_group
|
|
401
|
+
except KeyError as k:
|
|
402
|
+
print("[create_comp_group]:", k)
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def add_comp_group(scene: bpy.types.Scene, data: PYDict) -> BGroup:
|
|
407
|
+
"""Create compositor node group and add to scene.
|
|
408
|
+
|
|
409
|
+
:param scene: Scene to add compositor node group to.
|
|
410
|
+
:type scene: Scene
|
|
411
|
+
:param data: Data dict to build compositor node group.
|
|
412
|
+
:type data: dict[str, Any]
|
|
413
|
+
:return: Compositor NodeGroup.
|
|
414
|
+
:rtype: NodeGroup"""
|
|
415
|
+
scene.compositing_node_group = None
|
|
416
|
+
node_group = create_comp_group(data['node_groups'])
|
|
417
|
+
scene.compositing_node_group = node_group
|
|
418
|
+
return node_group
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
####################### TEXTURE ########################
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
@register_ng_setter('TextureNodeTree')
|
|
425
|
+
def create_texture_group_from_data(data: PYDict) -> BGroup:
|
|
426
|
+
"""Create a node group from build data.
|
|
427
|
+
|
|
428
|
+
:param data: Dictionary containing data to build node grouo.
|
|
429
|
+
:type data: dict[str, Any]
|
|
430
|
+
:return: NodeGroup.
|
|
431
|
+
:rtype: NodeGroup"""
|
|
432
|
+
node_group = create_node_group_from_data(data, group_type='TextureNodeTree')
|
|
433
|
+
return node_group
|
node_to_json/py.typed
ADDED
|
File without changes
|