OpScript Update AOVs
If you are new to Lua for Katana or Lua in general, the foundry has a great set of videos here , also this video by Trixter Film. And as always check out the developer guides for more information.
With that out of the way. I was messing around in Katana trying to figure out workflow ideas and I came up with an opscript to force the lights in your gaffer to match based on the names of the parent rigs. Why would you want this? Mostly as a fail safe. In a perfect world when you create lights you should be setting the AOVs but sometimes we forget. Or during setup we reorganize the gaffer and forget to go in and rename things. Or you name it but there’s a spelling mistake and then its not showing up as expected inside your compositing software.
Here’s a break down of my opscript to solve some of those problems. Hope you find it useful!
*This is using the Arnold render engine. the attribute names for the lights aovs will be different based on your render engine.
--:::::::::::::::::::::::::::: --:::: Light Annotations :::: --:::::::::::::::::::::::::::: -- Robert Matier -- Version: 1..0 -- Last Updated: 2025/06/02 --:::: UPDATES -- Katana OpScript designed to force light aovs to predefined patterns -- Works by running through all the elements of type 'light' under the main rig -- Checks the AOVs and potetntially reassigns the values based on parent rig names -- checkbox to enable annotations to see the changes --limitations : requires working in the specific predefined workflow -- -- variable setup local enableAnno = Interface.GetOpArg('user.enableAnnotation') local enableAnnoVal = math.floor(enableAnno:getValue()) local approvedAovNames = {"LG_A","LG_B","LG_C","LG_D","LG_E","LG_F"} --adjust as needed local search = 'LG_' local lgRigFull = Interface.GetInputLocationPath() local type = Interface.GetInputLocationType(lgRigFull) local lg = Interface.GetAttr('material.arnoldLightParams.aov') local index = pystring.find(lgRigFull, search) -- looking for LG_ in path --logic if index > 0 then -- the light is under a parent rig with the correct naming if lg then -- the aov isn't nil local checkLg = string.sub(lgRigFull, index +4, index +4) --we are looking for 'LG_*' and then getting the 4th character lua starts a t 1 not 0 local lgVal = lg:getValue() if lgVal == checkLg then -- name matches the parent rig name local lgVal = lg:getValue() Interface.SetAttr("viewer.default.annotation.text", lg) Interface.SetAttr('viewer.default.annotation.color', FloatAttribute({0.0,1.0,0.0})) elseif lgVal ~= checkLg then -- name doesn't match the parent rig local message = 'aov changed from ' .. lgVal .. ' to ' .. checkLg Interface.SetAttr("viewer.default.annotation.text", StringAttribute(message)) Interface.SetAttr('viewer.default.annotation.color', FloatAttribute({1.0,1.0,0.0})) end else local index = pystring.find(lgRigFull, search) -- looking for LG_ in path if index > 0 then --there is no local aov assigned. will use parent rig name local rigLg = string.sub(lgRigFull, index +4, index +4) local message = 'aov not set using heirachy ' .. rigLg Interface.SetAttr("viewer.default.annotation.text", StringAttribute(message)) Interface.SetAttr('viewer.default.annotation.color', FloatAttribute({1.0,0.5,0.0})) end end else if lg then --the aov isn't nil local lgVal = lg:getValue() local message = 'not in heirachy using local aov ' .. lgVal Interface.SetAttr("viewer.default.annotation.text", StringAttribute(message)) Interface.SetAttr('viewer.default.annotation.color', FloatAttribute({1.0,0.0,0.0})) else --there is no local aov local message = 'NO AOV ASSIGNED' Interface.SetAttr("viewer.default.annotation.text", StringAttribute(message)) Interface.SetAttr('viewer.default.annotation.color', FloatAttribute({0.0,0.0,0.0})) end end if enableAnnoVal == 0 then Interface.SetAttr("viewer.default.annotation.text", nil) Interface.SetAttr("viewer.default.annotation.color", nil) end
If everything goes as expected we should be seeing something like this.
Green - AOV existed and matched the Lettered Rig location - using local AOV value
Yellow - AOV existed but did not match the Lettered Rig location - AOV gets updated to Lettered Rig
Orange - AOV did not exist but Lettered Rig location exists - AOV gets updated to Lettered Rig
Red - AOV existed but not under a Lettered Rig - using local AOV value
Black - AOV did not exist and Lettered Rig location does not exist - no action
NOT DISPLAYED THE USER CHECKBOX TO TOGGLE THE ANNOTATIONS ON
The way I have it setup we are expecting aovs that are a single capital letter (A,B,C,…,Z ; technically in the example i only go up to F in the approved names) these aovs should live under a rig that follows the naming convention ‘LG_’ and then a capital letter. They may be nested inside several rigs but eventually in the hierarchy they should have one of those Lettered Rigs as a parent. With this setup in mind we can check the aov attributes and compare that to the scene graph location.