Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# Copyright 2015 Théo Friberg under GNU GPL 3
import json
def readNodes(file):
with open(file, "r") as data_file:
return json.load(data_file)
def inflateFile(mat, fileToInflate, x=0, y=0):
"""
This method sets up a material saved to a JSON file. It returns a dictionary of
nodes with their labels as keys. The nodes are added to the specified material.
_Usage_: inflateFile(<reference to material the nodes are added to>,
<path of the file to load>, [optional <translation of the final node setup on the x axis>, <translation of the final node setup on the y axis>])
The syntax of the JSON file must be as follows:
1. Opening declaration (this may later be extended to create operators automatically and contain operator metadata):
{
"NodeSetup":[
2. Nodes as follows
{
"label": "<label for the node>", - the node's mandatory identifier
"type": "<the type of the node>, - the node's type (mandatory)
"location": [<x>, <y>], - the node's mandatory location
"in": [
[<node>, <output>, (mandatoy) <input>],
<etc.>
] - (optional) Links going in to the node. Parameters:
* The node whose output we take
* Which output we take (can either be the display name, or
the index of the output. In the former case, must be written
as such: "\"<name>\"". In the later case, can be written as
either <index> or "<index>".)
* (optional) The input the connection goes into. The syntax is
as per above. If omitted, links go into inputs in numerical
order from top to bottom.
},
<etc.>
Note: Nodes can be accessed in more depth. For accessing the blend_mode of
a MixRGB, for example, one would write eg. (python):
<node>.blend_mode = "MULTIPLY"
From JSON, this can be written as:
"blend_mode": "\"MULTIPLY\""
For setting default values of inputs, use the following syntaxes:
"inputs[0].default_value": 1
or
"inputs[\"Color\"].default_value": [0, 1, 0, 1]
3. Closing declaration as follows:
]
}
The file is read using Python's built-in JSON parser, so indentation or line breaks are optional."""
# Variables for the parsed JSON array, the nodes added and all the
# nodes in the material, respectively.
nodes_JSON = readNodes(fileToInflate)
nodes_dict = {}
nodes = mat.node_tree.nodes
# We iterate a first time to create the nodes with their settings
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
for node in nodes_JSON["NodeSetup"]:
technical_name = node["type"]
location = node["location"]
nodes_dict[node["label"]] = nodes.new(technical_name)
nodes_dict[node["label"]].location = (node["location"][0]+x,
node["location"][1]+y)
nodes_dict[node["label"]].name = node["label"]
nodes_dict[node["label"]].label = node["label"]
# The nodes' parameters can be generic, runnable Python.
# This requires us to actually execute part of the files.
for attribute in node.keys():
if attribute not in ("in", "label", "type", "location"):
exec("nodes_dict[node[\"label\"]]."+ attribute + " = " +
str(node[attribute]))
# We create the links between the nodes
# The syntax in the json is the following
# "in": [
# ["<what node is plugged in>", <which of the nodes outputs is used, can be
# either string, as in "\"Color\"" or number, eg. 0 for the first output.>,
# <what input is this plugged to. Can be omitted for sequentially filling all
# inputs. If this has a value, it works like the previous value.>],
# <next inputs etc.>
# ]
links = mat.node_tree.links
for node in nodes_JSON["NodeSetup"]:
if "in" in node.keys(): # Does the node have links?
i = 0
while i < len(node["in"]): # We iterate over the links
# Is a specific input specified?
if len(node["in"][i]) == 3:
# Contruct and execute the line adding a link
exec ("links.new(nodes_dict[\"" + node["in"][i][0] +
"\"].outputs[" + str(node["in"][i][1]) +
"], nodes_dict[\"" + node["label"] + "\"].inputs["
+ str(node["in"][i][2]) + "])")
else:
# We don't have a specific input to hook up to
exec ("links.new(nodes_dict[\"" + node["in"][i][0] +
"\"].outputs[" + str(node["in"][i][1]) +
"], nodes_dict[\"" + node["label"] + "\"].inputs["
+ str(i) + "])")
i += 1
# We return the nodes for purposes of further access to them