Getting Started¶
Folder structure¶
nuketemplate
is a wrapper around the Jinja 2 templating engine. If you are
not familiar with Jinja 2 templates, read the documentation Jinja 2.
Let’s start with a simple template structure. Create a folder structure, like so:
/attrs
main.j2
attrs_write.j2
/nodes
main.j2
nodes.j2
The main.j2
file is the root template in which we will include all other
sub templates (attrs_write.j2
and nodes.j2
).
Defining attributes¶
The final format of all attributes must be a valid JSON object so make sure the
aggregator in /attrs/main.j2
is a valid JSON object {}
.
Add the following code snippet to /attrs/main.j2
. This code will parse
every file in the same folder that has a file name starting with attrs_
and
include it in the final set of attributes. That means it is very easy to extend
by simply creating additional files with the same naming pattern.
{
{% for attr_template in attr_templates %}
{% include attr_template | basename %}
{% if not loop.last %},{% endif %}
{% endfor %}
}
Add the following code snippet to /attrs/attrs_write.j2
. Again, this will
be included in the JSON object in /attrs/main.j2
.
"output": {
"flat": {
"channels": "rgb",
"file_type": "jpg",
"_jpeg_quality": 1.0,
"_jpeg_sub_sampling": "4:4:4",
"colorspace": "sRGB"
},
"layered": {
"channels": "rgba",
"file_type": "png",
"datatype": "8 bit",
"colorspace": "sRGB"
}
}
Defining Node Graphs in Templates¶
Add the following code snippet to /nodes/main.j2
. This will reference the
sub template nodes.j2
and include it in the list of sub templates.
[
{% include "nodes.j2" %}
]
Note
The final format of all nodes must be a valid JSON object so make sure the
aggregator in /nodes/main.j2
is a valid JSON object []
.
To add further sub templates simply extend the list with further include
directives.
Add the following code snippet to /nodes/nodes.j2
.
{
">>": "write",
"write": {
"type": "Write",
"inputs": ["cutout"],
"attr": {{ attrs["output"]["layered"] | tojson }},
"id": {{ id_data | tojson }}
},
"cutout": {
"type": "Premult",
"inputs": ["alpha"]
},
"alpha": {
"type": "Shuffle",
"inputs": ["<<"]
}
}
This is a simple sub template in the standard format. The first item is the
start
indicator, which tells the
AbstractTemplateConverter
which node to start
with. The standard key to indicate the start
value is >>
but this can
be freely defined in the
AbstractTemplateConverter
constructor.
One node in the template will have to have the end
indicator as one of its
inputs (the default is <<
but this can be redefined in the
AbstractTemplateConverter
constructor).
This indicates where the sub graph will be connected to the next sub graph in
the list.
Conceptually it is best to think about this node graph as a Nuke graph
“upside-down”, the start
node being the last node in the graph.
A node in the template format must implement the following format:
node name: {
type: Nuke node type,
inputs: List of inputs from the same subgraph,
attr: {
Nuke attribute: value
},
id: {
UUID type: UUID
}
}
Note
The attr
and id
keys are optional and will be ignored if not
specified.
All values can be substituted using Jinja 2 templating, like in the example.
Note
Use the tojson
filter to ensure values are converted to valid JSON
Building the Nuke Node Graph¶
With the templates in place, start Nuke and import the following
nuketemplate
classes:
from nuketemplate.template import AbstractTemplate
from nuketemplate.convert import AbstractTemplateConverter
from nuketemplate.build import NukeGraphBuilder
Initialise an AbstractTemplate
like so:
template = AbstractTemplate(root='/path/to/template/folder')
Since we have specified the variable id_data
in our template, we will
have to supply this data.
data = {'id_data': {'uuid': '3a5c2055-e288-4bc2-90cb-dc0fb9ae462e'}}
Now, pass the data to the
render()
function, like so:
template.render(**data)
After template rendering, initialise a
AbstractTemplateConverter
and run the
convert()
function,
like so:
converter = AbstractTemplateConverter(template.template)
converter.convert()
To build the Nuke node graph, initialise a
NukeGraphBuilder
and run the
build()
function,
like so:
builder = NukeGraphBuilder(converter.result)
builder.build()