The basic skeleton of a script in such a graph looks like this:
- Code: Select all
local MyGraphScript = {}
function MyGraphScript.onInit(self, graph)
end
function MyGraphScript.onEvaluate(self, graph)
return true
end
return MyGraphScript
Running this script will not do any work, but it will create a table (called
MyGraphScript
), fill in some values and return the table. Octane will then add a metatable to this table, so you can call the methods from the octane.scriptgraph using the colon syntax.onInit
is a function, it's called once after the graph is loaded, or after the script is changed. It receives two arguments: the first argument is the table which was returned from this script, the second one is the node graph.onEvaluate
will be called every time one of the input values changes. As with any node graph, the inputs are defined by input linker nodes. It should usually return true, it should return false only if you decide that an input change doesn't have any effect.So let's now create a script which actually does something. We will create one texture input which should get an RGB color, and one output which is the color with the hue rotated 120°.
First we create the table we are going to return:
- Code: Select all
local MyGraphScript = {}
Now, the onInit function will create all the nodes in the graph. We need some of these in our onEvaluate function to update values. One way to keep references is declaring some references in the scope of our script.
- Code: Select all
-- variables declared in the script scope are visible for all functions in our
-- script for as long as the scripted graph is not deleted or reloaded (in
-- programming terms, our two functions become "closures").
local inputs, tex
-- onInit function, this is called once in the beginning.
function MyGraphScript.onInit(self, graph)
-- input and output infos
local inputInfos = {
{type=octane.PT_TEXTURE, label="RGB", defaultNodeType=octane.NT_TEX_RGB}
}
local outputInfos = {
{type=octane.PT_TEXTURE, label="RGB"}
}
-- use these functions to set up input and output linkers. This will keep
-- existing linkers so existing connections in the parent graph are kept.
inputs = graph:setInputLinkers(inputInfos)
local outputs = graph:setOutputLinkers(outputInfos)
-- set up a node to give the graph some output value
tex = octane.node.create{ type=octane.NT_TEX_RGB, name="color", graphOwner=graph }
outputs[1]:connectTo("input", tex)
end
Let's go over this step by step:
Before the onInit function is called, Octane will always make sure the node graph is empty, except for the linker nodes. Keeping the linker nodes ensures that if there are nodes connected to the scripted graph, these connections are not broken by reloading the script. For this reason the script should not destroy and create the linkers. Therefore the API provides two new functions in the octane.nodegraph module to set up linker nodes,
setInputLinkers
and setOutputLinkers
.First we define two arrays of tables,
inputInfos
and outputInfos
, which specify which linker nodes we want. The minimal information is the node pin type, and the label for the input or output. For input linkers you can also specify extra information, like the default node type, the minimum and maximum values etc. For value inputs (int, float, bool, transform and texture) you should always at least specify the default node type.Then we call the
setInputLinkers
and setOutputLinkers
functions, to set up the linker nodes. These functions will automatically keep existing linkers if possible. They return the list of linker nodes.Finally we create an RGB texture node and connect it to the output linker.
The onEvaluate function is called whenever the input value of our input linker changes:
- Code: Select all
-- this function is called every time the value of an input linker changes
function MyGraphScript.onEvaluate(self, graph)
-- the scriptgraph object has a special function to read input values
local rgb = self:getInputValue(inputs[1])
-- set some output value. (for example, rotate the RGB channels)
tex:setAttribute("value", {rgb[3], rgb[1], rgb[2]})
end
This function reads the value from the input linker. Note that normally you can't read a value via the input pin of a linker node. In scripted graphs you can use the
getInputValue
function, and it updates the value attribute on the RGB texture node.So, finally, what's up with these
inputs
and tex
variables? These are declared in the scope of the script. Remember that the script is just run in the beginning to set up the table, so these variables go out of scope after we return the table. But we use the variables in the onInit
and onEvaluate
functions. When this happens, Lua will keep the values so the functions can use them if they are called later.Most of the stuff is documented in the
octane.graphscript
module except for the pin information, I'll make another post for that.--
Roeland