After 3 years of Python scripting, I finally reached that point where I can confidently say that I roughly know, what I am doing. Then I fall in love with Katana and while interface and node graph stuff can be accessed/modified via Python, OpScripts are – for some reason – Lua based.
Well, off to something new then. tongue
I consider this blog post as a dynamic place that I will update whenever I make some progress. I am not sure how this will turn out, but I think I’ll start off with some code snippets. Although code snippet sounds too ambitious bigsmile Let’s call it one-liners. If anybody stumbles upon this, feel free to leave a comment, correct me, help me, suggest anything you think that might be useful. I would greatly appreciate it.
Some Lua syntax that is different from Python
My first impression: Lua has somehow similar syntax to Python but there are enough differences to make this confusing. So here is my Python to Lua cheat sheet:
Miscellaneous
--single line comment in lua --[[ what the f* is this? I need to get rid of my german keyboard or never use multiline comments in lua... --]] print('parentheses are mandatory as in python 3') --not equal in lua ~= --true and false is lowercase --None is Nil in Lua
Variables
--variables are global by default, they can be made local with local local var = 20 local my_string = "string with double quotes" local another_string = 'single quotes work just as well - sweet!' local string_concatenation = my_string .. another_string
if and for
if and for syntax reminds me of good ol’ max script. Since Lua doesn’t rely on indentations it requires simple keywords instead like “do”, “then” or “end”. “elif” becomes the slightly longer “elseif”.
--if expression if var == 20 then print ('this is equal') elseif var > 20 then print ('this is larger') else print ('then it must be smaller') end --for loop for start, end, step do something end --this starts at 2 and increments by 1 until 5 for i=2, 5, 1 do print(i) end
lists, arrays, dicts = tables
lua has meta-mechanism. For example python doesn’t have a native array, but you can use lists to make one. Lua goes a step further. Lua just has tables which could behave like a list, an array or even a dict, depending on how you define/use it.
--index starts at 1 not 0 --curly brackets instead of square, however square ones for accessing it. local list = {1,2,3} print(list[2]) local array = {{1,2},{3,4}} print(array[2][1]) local dict = {first_key = 123, second_key = 456} print(dict.first_key) --yup, every one of those is just a table in Lua
OpScript in Katana
To create an OpScript in Katana, just create an OpScript node and define your CEL statements. The OpScript will now loop over the defined scene graph locations and run the code. As long as executionMode is “immediate” the code is run, whenever you “leave” the script box. That is, whenever you click somewhere else in the Interface. If you have some unfinished code which you know, would throw an error and you don’t want Katana to freak out, you can change this setting to deferred. Now the code is only run when you have either an OpResolve node, or you can conveniently toggle Scene Graph Implicit Resolvers from the top menu bar.
Now let’s start really simple.
--get an attribute Interface.GetAttr("material.parameters.color")
To find out the attribute name you usually just need to chain the group names
in the attributes panel with a dot. Alternatively you can hover over the attribute
and the tooltip shows the whole path.
--print an attribute to the shell to see if it worked local my_float = Interface.GetAttr("material.parameters.roughness") print (my_float)
However, this will return
FloatAttribute(0.734)
This might be what you want, or maybe not. If you want to do some calculations, you can use getValue() to get the actual value.
local my_float = Interface.GetAttr("material.parameters.color"):getValue() print (my_float) my_float = my_float + 0.1 print (my_float)
to be continued…