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,452 @@
|
|
|
1
|
+
from .type_util import PYDict, BNode, BGroup
|
|
2
|
+
from .node_registry import register_node_setter, bpy_types_funcs, BtypeFn
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
set_node_exclude = ['type', 'parent', 'inputs', 'outputs', 'bl_idname', 'object', 'image', 'material', 'scene']
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
#### HELPER FUNCS ####
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def set_node_attr(node: BNode, attr: PYDict, *args: str) -> None:
|
|
12
|
+
for a in attr:
|
|
13
|
+
if not isinstance(attr[a], dict):
|
|
14
|
+
try:
|
|
15
|
+
if hasattr(node, a) and not isinstance(attr[a], type(None)) and a not in set_node_exclude + list(args):
|
|
16
|
+
if a == 'location' and attr['parent'] in [None, '']:
|
|
17
|
+
continue
|
|
18
|
+
else:
|
|
19
|
+
setattr(node, a, attr[a])
|
|
20
|
+
except Exception as e:
|
|
21
|
+
continue
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def set_nested_attr(node: BNode, attr: str, data: PYDict, *args: str) -> object | None:
|
|
25
|
+
if hasattr(node, attr):
|
|
26
|
+
_attr = getattr(node, attr, None)
|
|
27
|
+
if _attr:
|
|
28
|
+
set_node_attr(_attr, data[attr], *args)
|
|
29
|
+
return _attr
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def set_listed_attr(node: BNode, attr: str, data: PYDict) -> object:
|
|
34
|
+
if hasattr(node, attr):
|
|
35
|
+
_attr = getattr(node, attr, None)
|
|
36
|
+
if _attr:
|
|
37
|
+
_attr.clear()
|
|
38
|
+
if data[attr] not in [None, [], '']:
|
|
39
|
+
for idx, i in enumerate(data[attr]):
|
|
40
|
+
_attr.new(i['socket_type'], i['name'])
|
|
41
|
+
for a in i:
|
|
42
|
+
if hasattr(_attr, a) and not isinstance(data[attr][idx][a], type(None)) and a not in ['socket_type', 'name']:
|
|
43
|
+
setattr(_attr, a, data[attr][idx][a])
|
|
44
|
+
return _attr
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def set_enum_attr(node: BNode, attr: str, data: PYDict) -> object:
|
|
48
|
+
if hasattr(node, attr):
|
|
49
|
+
_attr = getattr(node, attr, None)
|
|
50
|
+
if _attr:
|
|
51
|
+
_attr.clear()
|
|
52
|
+
for idx, i in enumerate(data[attr]):
|
|
53
|
+
_attr.new(i['name'])
|
|
54
|
+
for a in i:
|
|
55
|
+
if hasattr(_attr, a) and not isinstance(data[attr][idx][a], type(None)) and a not in ['name']:
|
|
56
|
+
setattr(_attr, a, data[attr][idx][a])
|
|
57
|
+
return _attr
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def set_capture_listed_attr(node: BNode, attr: str, data: PYDict) -> object:
|
|
61
|
+
if hasattr(node, attr):
|
|
62
|
+
_attr = getattr(node, attr, None)
|
|
63
|
+
if _attr:
|
|
64
|
+
_attr.clear()
|
|
65
|
+
for idx, i in enumerate(data[attr]):
|
|
66
|
+
_attr.new(i['data_type'], i['name'])
|
|
67
|
+
for a in i:
|
|
68
|
+
if hasattr(_attr, a) and not isinstance(data[attr][idx][a], type(None)) and a not in ['data_type', 'name']:
|
|
69
|
+
setattr(_attr, a, data[attr][idx][a])
|
|
70
|
+
return _attr
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def set_bpy_collection(ob: BNode, attr: PYDict, *default_data: float) -> None:
|
|
74
|
+
for i in range(len(ob) - 1):
|
|
75
|
+
ob.remove(ob[i])
|
|
76
|
+
if hasattr(ob, 'update'):
|
|
77
|
+
ob.update()
|
|
78
|
+
for i in range(len(attr) - 1):
|
|
79
|
+
ob.new(*default_data)
|
|
80
|
+
if hasattr(ob, 'update'):
|
|
81
|
+
ob.update()
|
|
82
|
+
for idx, e in enumerate(attr):
|
|
83
|
+
for a in e:
|
|
84
|
+
if hasattr(ob[idx], a) and not isinstance(attr[idx][a], type(None)):
|
|
85
|
+
try:
|
|
86
|
+
setattr(ob[idx], a, attr[idx][a])
|
|
87
|
+
except Exception as e_:
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def set_loop_items_attr(node: BNode, attr: str, data: PYDict) -> None:
|
|
92
|
+
_items = getattr(node, attr, None)
|
|
93
|
+
if _items:
|
|
94
|
+
_items.clear()
|
|
95
|
+
for a in data[attr]:
|
|
96
|
+
ii = _items.new(a['socket_type'], a['name'])
|
|
97
|
+
if hasattr(ii, 'structure_type') and 'structure_type' in list(a.keys()):
|
|
98
|
+
ii.structure_type = a['structure_type']
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def set_node_from_data(node: BNode, attr: PYDict, group_dict: dict[str, BGroup]) -> BtypeFn | None:
|
|
102
|
+
"""Set attributes for a node from data.
|
|
103
|
+
|
|
104
|
+
:param node: Node to set data to.
|
|
105
|
+
:type node: Node
|
|
106
|
+
:param attr: Data used to set attributes.
|
|
107
|
+
:type attr: dict[str, Any]
|
|
108
|
+
:param group_dict: Dict of all node groups in the main node group.
|
|
109
|
+
:type group_dict: dict[str, Node Group]
|
|
110
|
+
:return: Function to set node attributes.
|
|
111
|
+
:rtype: Function | None"""
|
|
112
|
+
_func = bpy_types_funcs.get(node.bl_idname)
|
|
113
|
+
if _func is None:
|
|
114
|
+
try:
|
|
115
|
+
if node.bl_idname in ['GeometryNodeCustomGroup', 'GeometryNodeGroup', 'ShaderNodeCustomGroup', 'ShaderNodeGroup', 'NodeGroup', 'TextureNodeGroup', 'CompositorNodeCustomGroup', 'CompositorNodeGroup']:
|
|
116
|
+
set_geo_group(node, attr, group_dict)
|
|
117
|
+
else:
|
|
118
|
+
set_node_attr(node, attr)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
pass
|
|
121
|
+
else:
|
|
122
|
+
_func(node, attr)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
#######################################################################################################
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
#### COLOR RAMP ####
|
|
129
|
+
def set_color_ramp_attr(node, attr):
|
|
130
|
+
color_ramp = getattr(node, 'color_ramp', None)
|
|
131
|
+
if color_ramp:
|
|
132
|
+
set_node_attr(color_ramp, attr['color_ramp'], 'elements')
|
|
133
|
+
elements = getattr(color_ramp, 'elements', None)
|
|
134
|
+
if elements:
|
|
135
|
+
set_bpy_collection(elements, attr['color_ramp']['elements'], 0.0)
|
|
136
|
+
elements.update()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
#### IMAGE USER ####
|
|
140
|
+
def set_img_user_attr(node, attr):
|
|
141
|
+
set_nested_attr(node, 'image_user', attr)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
#### TEXTURE MAPPING ####
|
|
145
|
+
def set_tex_mapping_attr(node, attr):
|
|
146
|
+
set_nested_attr(node, 'texture_mapping', attr)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
#### COLOR MAPPING ####
|
|
150
|
+
def set_col_mapping_attr(node, attr):
|
|
151
|
+
color_mapping = getattr(node, 'color_mapping', None)
|
|
152
|
+
if color_mapping:
|
|
153
|
+
set_node_attr(color_mapping, attr['color_mapping'], 'color_ramp', 'elements')
|
|
154
|
+
if attr['color_mapping']['use_color_ramp']:
|
|
155
|
+
set_color_ramp_attr(color_mapping, attr['color_mapping'])
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
#### CURVE MAPPING ####
|
|
159
|
+
def set_curve_mapping_attr(node, attr, mapping_='mapping'):
|
|
160
|
+
mapping = set_nested_attr(node, mapping_, attr, 'curves')
|
|
161
|
+
if mapping:
|
|
162
|
+
curves = getattr(mapping, 'curves', None)
|
|
163
|
+
if curves:
|
|
164
|
+
ct = len(curves)
|
|
165
|
+
for idx, pt in enumerate(attr[mapping_]['curves']):
|
|
166
|
+
if idx < ct:
|
|
167
|
+
points = curves[idx].points
|
|
168
|
+
pct = len(points)
|
|
169
|
+
_pct = len(attr[mapping_]['curves'][idx]['points'])
|
|
170
|
+
_ct = pct - _pct
|
|
171
|
+
for p in range(_ct):
|
|
172
|
+
try:
|
|
173
|
+
points.remove(points[p])
|
|
174
|
+
except Exception as e:
|
|
175
|
+
continue
|
|
176
|
+
points.update()
|
|
177
|
+
for p in range(abs(_ct)):
|
|
178
|
+
points.new(.5, .5)
|
|
179
|
+
points.update()
|
|
180
|
+
for ij, j in enumerate(attr[mapping_]['curves'][idx]['points']):
|
|
181
|
+
for _a in j:
|
|
182
|
+
if hasattr(points[ij], _a) and not isinstance(j[_a], type(None)):
|
|
183
|
+
setattr(points[ij], _a, j[_a])
|
|
184
|
+
curves.update()
|
|
185
|
+
mapping.update()
|
|
186
|
+
if hasattr(node, 'update'):
|
|
187
|
+
node.update()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
#### LOOP INPUT ####
|
|
191
|
+
def set_loop_input_attr(node, attr):
|
|
192
|
+
if attr['paired_output'] not in [None, '']:
|
|
193
|
+
node.pair_with_output(node.id_data.nodes[attr['paired_output']['name']])
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
#### CURVE TIME ####
|
|
197
|
+
def set_curve_time_attr(node, attr):
|
|
198
|
+
curve = getattr(node, 'curve', None)
|
|
199
|
+
if curve:
|
|
200
|
+
set_curve_mapping_attr(curve, attr['curve'], mapping_='curve')
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
#### IMAGE FORMAT SETTINGS ####
|
|
204
|
+
def set_image_format_settings(img_form, attr):
|
|
205
|
+
set_node_attr(img_form, attr, 'display_settings', 'linear_colorspace_settings', 'stereo_3d_format', 'view_settings')
|
|
206
|
+
disp_sett = getattr(img_form, 'display_settings', None)
|
|
207
|
+
if disp_sett:
|
|
208
|
+
set_node_attr(disp_sett, attr['display_settings'])
|
|
209
|
+
cs_sett = getattr(img_form, 'linear_colorspace_settings', None)
|
|
210
|
+
if cs_sett:
|
|
211
|
+
set_node_attr(cs_sett, attr['linear_colorspace_settings'])
|
|
212
|
+
s3d_sett = getattr(img_form, 'stereo_3d_format', None)
|
|
213
|
+
if s3d_sett:
|
|
214
|
+
set_node_attr(s3d_sett, attr['stereo_3d_format'])
|
|
215
|
+
view_sett = getattr(img_form, 'view_settings', None)
|
|
216
|
+
if view_sett:
|
|
217
|
+
set_node_attr(view_sett, attr['view_settings'], 'curve_mapping', 'is_hdr', 'support_emulation')
|
|
218
|
+
if attr['view_settings']['use_curve_mapping']:
|
|
219
|
+
set_curve_mapping_attr(view_sett, attr['view_settings']['curve_mapping'], mapping_='curve_mapping')
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
#######################################################################################################
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
#### COLOR RAMP ####
|
|
226
|
+
@register_node_setter('ShaderNodeValToRGB', 'TextureNodeValToRGB')
|
|
227
|
+
def set_color_ramp(node, attr):
|
|
228
|
+
set_node_attr(node, attr, 'color_ramp', 'elements')
|
|
229
|
+
set_color_ramp_attr(node, attr)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
#### COLOR MAPPING, TEXTURE MAPPING, IMAGE USER ####
|
|
233
|
+
@register_node_setter('ShaderNodeTexWave', 'ShaderNodeTexVoronoi', 'ShaderNodeTexSky', 'ShaderNodeTexNoise', 'ShaderNodeTexMagic', 'ShaderNodeTexImage', 'ShaderNodeTexGradient', 'ShaderNodeTexGabor', 'ShaderNodeTexEnvironment', 'ShaderNodeTexChecker', 'ShaderNodeTexBrick')
|
|
234
|
+
def set_img_col_tex_mapping(node, attr):
|
|
235
|
+
set_node_attr(node, attr, 'color_mapping', 'color_ramp', 'elements', 'texture_mapping', 'image_user')
|
|
236
|
+
if hasattr(node, 'image_user'):
|
|
237
|
+
set_img_user_attr(node, attr)
|
|
238
|
+
if hasattr(node, 'texture_mapping'):
|
|
239
|
+
set_tex_mapping_attr(node, attr)
|
|
240
|
+
if hasattr(node, 'color_mapping'):
|
|
241
|
+
set_col_mapping_attr(node, attr)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
#### CURVE MAPPING ####
|
|
245
|
+
@register_node_setter('ShaderNodeVectorCurve', 'ShaderNodeRGBCurve', 'ShaderNodeFloatCurve', 'TextureNodeCurveRGB', 'CompositorNodeCurveRGB', 'CompositorNodeHueCorrect')
|
|
246
|
+
def set_curve_mapping(node, attr):
|
|
247
|
+
set_node_attr(node, attr, 'curves', 'points', 'mapping')
|
|
248
|
+
set_curve_mapping_attr(node, attr)
|
|
249
|
+
node.update()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
#### BAKE ####
|
|
253
|
+
@register_node_setter('GeometryNodeBake')
|
|
254
|
+
def set_bake(node, attr):
|
|
255
|
+
set_node_attr(node, attr, 'bake_items')
|
|
256
|
+
node.bake_items.clear()
|
|
257
|
+
for idx, a in enumerate(attr['bake_items']):
|
|
258
|
+
if a['socket_type'] == 'CUSTOM':
|
|
259
|
+
node.inputs[idx].hide = attr['inputs'][idx]['hide']
|
|
260
|
+
node.outputs[idx].hide = attr['outputs'][idx]['hide']
|
|
261
|
+
else:
|
|
262
|
+
bake = node.bake_items.new(a['socket_type'], a['name'])
|
|
263
|
+
bake.attribute_domain = a['attribute_domain']
|
|
264
|
+
bake.is_attribute = a['is_attribute']
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
#### REPEAT, FOREACH, SIMULATION, CLOSURE ####
|
|
268
|
+
@register_node_setter('GeometryNodeRepeatInput', 'GeometryNodeForeachGeometryElementInput', 'GeometryNodeSimulationInput', 'NodeClosureInput')
|
|
269
|
+
def set_loop_input(node, attr):
|
|
270
|
+
set_node_attr(node, attr, 'paired_output')
|
|
271
|
+
set_loop_input_attr(node, attr)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
#### REPEAT ####
|
|
275
|
+
@register_node_setter('GeometryNodeRepeatOutput')
|
|
276
|
+
def set_repeat_output(node, attr):
|
|
277
|
+
set_node_attr(node, attr, 'repeat_items')
|
|
278
|
+
set_loop_items_attr(node, 'repeat_items', attr)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
#### FOREACH ####
|
|
282
|
+
@register_node_setter('GeometryNodeForeachGeometryElementOutput')
|
|
283
|
+
def set_foreach_output(node, attr):
|
|
284
|
+
set_node_attr(node, attr, 'input_items', 'main_items', 'generation_items')
|
|
285
|
+
set_loop_items_attr(node, 'input_items', attr)
|
|
286
|
+
set_loop_items_attr(node, 'main_items', attr)
|
|
287
|
+
set_loop_items_attr(node, 'generation_items', attr)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
#### SIMULATION ####
|
|
291
|
+
@register_node_setter('GeometryNodeSimulationOutput')
|
|
292
|
+
def set_sim_output(node, attr):
|
|
293
|
+
set_node_attr(node, attr, 'state_items')
|
|
294
|
+
set_loop_items_attr(node, 'state_items', attr)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
#### CLOSURE ####
|
|
298
|
+
@register_node_setter('NodeClosureOutput')
|
|
299
|
+
def set_closure_output(node, attr):
|
|
300
|
+
set_node_attr(node, attr, 'input_items', 'output_items')
|
|
301
|
+
set_loop_items_attr(node, 'input_items', attr)
|
|
302
|
+
set_loop_items_attr(node, 'output_items', attr)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
#### MENU ####
|
|
306
|
+
@register_node_setter('GeometryNodeMenuSwitch')
|
|
307
|
+
def set_menu(node, attr):
|
|
308
|
+
set_node_attr(node, attr, 'enum_items')
|
|
309
|
+
set_enum_attr(node, 'enum_items', attr)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
#### VIEWER ####
|
|
313
|
+
@register_node_setter('GeometryNodeViewer')
|
|
314
|
+
def set_viewer(node, attr):
|
|
315
|
+
set_node_attr(node, attr, 'viewer_items')
|
|
316
|
+
set_listed_attr(node, 'viewer_items', attr)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
#### CAPTURE ####
|
|
320
|
+
@register_node_setter('GeometryNodeCaptureAttribute')
|
|
321
|
+
def set_capture_attr(node, attr):
|
|
322
|
+
set_node_attr(node, attr, 'capture_items')
|
|
323
|
+
node.capture_items.clear()
|
|
324
|
+
for idx, a in enumerate(attr['capture_items']):
|
|
325
|
+
ca = node.capture_items.new('FLOAT', a['name'])
|
|
326
|
+
ca.data_type = a['data_type']
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
#### FORMAT ####
|
|
330
|
+
@register_node_setter('NodeFunctionFormatStringItem')
|
|
331
|
+
def set_format(node, attr):
|
|
332
|
+
set_node_attr(node, attr, 'format_items')
|
|
333
|
+
set_loop_items_attr(node, 'format_items', attr)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
#### COMBINEBUNDLE, SEPARATEBUNDLE ####
|
|
337
|
+
@register_node_setter('NodeCombineBundle', 'NodeSeparateBundleItem')
|
|
338
|
+
def set_bundle(node, attr):
|
|
339
|
+
set_node_attr(node, attr, 'bundle_items')
|
|
340
|
+
set_loop_items_attr(node, 'bundle_items', attr)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
#### EVALUTECLOSURE ####
|
|
344
|
+
@register_node_setter('NodeEvaluateClosure')
|
|
345
|
+
def set_evalute_closure(node, attr):
|
|
346
|
+
set_node_attr(node, attr, 'input_items', 'output_items')
|
|
347
|
+
set_loop_items_attr(node, 'input_items', attr)
|
|
348
|
+
set_loop_items_attr(node, 'output_items', attr)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
#### GETGEOMETRYCOMPONENT ####
|
|
352
|
+
@register_node_setter('GeometryNodeGetGeometryComponent')
|
|
353
|
+
def set_geometry_component(node, attr):
|
|
354
|
+
set_node_attr(node, attr)
|
|
355
|
+
inputs = getattr(node, 'inputs', None)
|
|
356
|
+
if inputs:
|
|
357
|
+
inputs[1].default_value = attr['inputs'][1]['default_value']
|
|
358
|
+
inputs[2].default_value = attr['inputs'][2]['default_value']
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
#### CURVE TIME ####
|
|
362
|
+
@register_node_setter('TextureNodeCurveTime', 'CompositorNodeTime')
|
|
363
|
+
def set_curve_time(node, attr):
|
|
364
|
+
set_node_attr(node, attr)
|
|
365
|
+
set_curve_time_attr(node, attr)
|
|
366
|
+
node.update()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
#### CLOSURETOLISTITEM ####
|
|
370
|
+
@register_node_setter('GeometryNodeClosureToListItems')
|
|
371
|
+
def set_closure_to_list(node, attr):
|
|
372
|
+
set_node_attr(node, attr, 'list_items')
|
|
373
|
+
node.list_items.clear()
|
|
374
|
+
for idx, a in enumerate(attr['list_items']):
|
|
375
|
+
ctl = node.list_items.new(a['socket_type'], a['name'])
|
|
376
|
+
ctl.structure_type = a['structure_type']
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
### CURVEHANDLETYPESELECTION ###
|
|
380
|
+
@register_node_setter('GeometryNodeCurveHandleTypeSelection', 'GeometryNodeCurveSetHandles')
|
|
381
|
+
def set_curve_handle_type_sel(node, attr):
|
|
382
|
+
set_node_attr(node, attr, 'mode')
|
|
383
|
+
node.mode = set(attr['mode'])
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
#### IMAGE ####
|
|
387
|
+
@register_node_setter('TextureNodeImage')
|
|
388
|
+
def set_image_attr(node, attr):
|
|
389
|
+
set_node_attr(node, attr, 'image_user')
|
|
390
|
+
set_img_user_attr(node, attr)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
#### GROUP ####
|
|
394
|
+
def set_geo_group(node, attr, group_dict):
|
|
395
|
+
if hasattr(node, 'node_tree'):
|
|
396
|
+
node.node_tree = group_dict[attr['node_tree']]
|
|
397
|
+
set_node_attr(node, attr, 'node_tree', 'node_group')
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
#### CONVERTTODISPLAY ####
|
|
401
|
+
@register_node_setter('CompositorNodeConvertToDisplay')
|
|
402
|
+
def set_convert_to_disp(node, attr):
|
|
403
|
+
set_node_attr(node, attr, 'curves', 'points', 'curve_mapping', 'display_settings', 'view_settings')
|
|
404
|
+
set_nested_attr(node, 'display_settings', attr)
|
|
405
|
+
view_settings = set_nested_attr(node, 'view_settings', attr, 'curve_mapping')
|
|
406
|
+
if attr['view_settings']["use_curve_mapping"]:
|
|
407
|
+
set_curve_mapping_attr(view_settings, attr['view_settings']['curve_mapping'], mapping_='curve_mapping')
|
|
408
|
+
node.update()
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
#### CRYPTOMATTEV2 ####
|
|
412
|
+
@register_node_setter('CompositorNodeCryptomatteV2')
|
|
413
|
+
def set_crytomatte_v2(node, attr):
|
|
414
|
+
set_node_attr(node, attr, 'entries', 'scene', 'has_layers', 'has_views')
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
#### IMAGE ####
|
|
418
|
+
@register_node_setter('CompositorNodeImage')
|
|
419
|
+
def set_comp_image(node, attr):
|
|
420
|
+
set_node_attr(node, attr, 'image', 'has_layers', 'has_views')
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
#### KEYING SCREEN ####
|
|
424
|
+
@register_node_setter('CompositorNodeKeyingScreen', 'CompositorNodeMovieClip', 'CompositorNodeMovieDistortion', 'CompositorNodePlaneTrackDeform', 'CompositorNodeStabilize', 'CompositorNodeTrackPos')
|
|
425
|
+
def set_keying_screen(node, attr):
|
|
426
|
+
set_node_attr(node, attr, 'clip')
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
#### MASK ####
|
|
430
|
+
@register_node_setter('CompositorNodeMask')
|
|
431
|
+
def set_comp_mask(node, attr):
|
|
432
|
+
set_node_attr(node, attr, 'mask')
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
#### OUTPUT FILE ####
|
|
436
|
+
@register_node_setter('CompositorNodeOutputFile')
|
|
437
|
+
def set_output_file(node, attr):
|
|
438
|
+
set_node_attr(node, attr, 'file_output_items', 'format')
|
|
439
|
+
_format = getattr(node, 'format', None)
|
|
440
|
+
if _format:
|
|
441
|
+
set_image_format_settings(_format, attr['format'])
|
|
442
|
+
node.file_output_items.clear()
|
|
443
|
+
for idx, a in enumerate(attr['file_output_items']):
|
|
444
|
+
if a['socket_type'] == 'CUSTOM':
|
|
445
|
+
node.inputs[idx].hide = attr['inputs'][idx]['hide']
|
|
446
|
+
node.outputs[idx].hide = attr['outputs'][idx]['hide']
|
|
447
|
+
else:
|
|
448
|
+
output_file = node.file_output_items.new(a['socket_type'], a['name'])
|
|
449
|
+
set_node_attr(output_file, a, 'color', 'format', 'name', 'socket_type')
|
|
450
|
+
set_image_format_settings(output_file, a['format'])
|
|
451
|
+
node.update()
|
|
452
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import bpy
|
|
2
|
+
|
|
3
|
+
type PYObject = int | str | float | bool | None
|
|
4
|
+
type PYContainer = list | tuple | set
|
|
5
|
+
type PYDict = dict[str | PYObject | list[PYObject] | dict[str | PYObject]]
|
|
6
|
+
type JSON = PYObject | dict[str | "JSON"] | list["JSON"]
|
|
7
|
+
type JSONObject = dict[str | JSON]
|
|
8
|
+
type JSONList = list[JSON]
|
|
9
|
+
type BNode = bpy.types.Node | object
|
|
10
|
+
type BGroup = bpy.types.GeometryNodeCustomGroup | bpy.types.GeometryNodeGroup | bpy.types.ShaderNodeCustomGroup | bpy.types.ShaderNodeGroup | bpy.types.NodeGroup | bpy.types.TextureNodeGroup | bpy.types.CompositorNodeCustomGroup | bpy.types.CompositorNodeGroup
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: node_to_json
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Blender 5.2 Serialize Node Groups to JSON files.Load Node Groups from JSON files.
|
|
5
|
+
Author: Demingo Hill (Noizirom) (C)
|
|
6
|
+
License-Expression: GPL-3.0-only
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# Node To JSON
|
|
11
|
+
|
|
12
|
+
## Convert Blender 5.2 Nodes to JSON files. Convert JSON objects to Blender Nodes.
|
|
13
|
+
### Created to work with Blender Addons and Extensions to serialize nodes. It is only intended to work within Blender's python interpreter and requires the bpy module.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
node_to_json/__init__.py,sha256=aQ9aoVLJBu-xT1CKPLltajT1Au18YRGdyf6WQAawUyo,2034
|
|
2
|
+
node_to_json/asset_funcs.py,sha256=M_qQitD5tgDT-0ggmfGjBQYieywhAmJptwxWnPZMnDg,2667
|
|
3
|
+
node_to_json/func_util.py,sha256=s3jbntColY5xvTrB5ICR0hPRcfxFDECQ2p4BxOsfmbA,3615
|
|
4
|
+
node_to_json/json_io.py,sha256=1bVT33h71f2wPtNfX5j99kMf04BKaNQSd0oC6YETPXU,892
|
|
5
|
+
node_to_json/node_getters.py,sha256=GXfCBvMnTnJOl0XYV9olchtcNS8y6JUSspQeP0M_dzE,17814
|
|
6
|
+
node_to_json/node_registry.py,sha256=nj9zGxKZwZzhfGGGWzmCkhFZWZTpj0cx3ohEgwtWJ4M,1734
|
|
7
|
+
node_to_json/node_setters.py,sha256=T_umv_399bEnKfll9ZO7AdvHzeo0X6jDsQ53-g12IAo,18674
|
|
8
|
+
node_to_json/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
node_to_json/setter_funcs.py,sha256=KKJvlqJ7PDRhAdv4GAdH6aC7P_cMI-UXk8opBOCo8JU,17096
|
|
10
|
+
node_to_json/type_util.py,sha256=2OZVBh2BlQuVhp6fOYflFeJvmzB3DKwb7yFHmDrTna8,598
|
|
11
|
+
node_to_json-0.1.1.dist-info/WHEEL,sha256=ZFFp7t7R4RYQ5KYZkmiFWoQvHay7SrTmn-6ZYfoFZ3U,80
|
|
12
|
+
node_to_json-0.1.1.dist-info/METADATA,sha256=4xKfGOjQRyTq59kURe03rkaNPmFXvA83tHPvXXmY0zs,550
|
|
13
|
+
node_to_json-0.1.1.dist-info/RECORD,,
|