If you want to change something in existing ASS files, don’t write an ad-hoc script or your own parser for the ASS file. Use the Arnold API. The Arnold API includes a set of Python bindings, so you can fairly quickly whip up a script to do whatever it is you need to do 🙂
For example, we recently discovered (and fixed) an issue where exported ASS files were missing procedural nodes. SItoA exports hair data in chunks (one chunk for every 200K hairs), but the exported ASS had just one procedural for the first chunk (chunk 0), but there should be one procedural for each chunk.
Here’s what the procedural for chunk 0 on frame 5 looks like. The missing procedurals would be for bin files like Hair.chunk.1.5.bin, Hair.chunk.2.5.bin, and so on.
procedural { name Hair.SItoA.5000 dso "sitoa_curves_proc.dll" data "//Projects/Support/Arnold_Scenes/Hair.chunk.0.5.bin" load_at_init on }
So, for my first dive into the Arnold API, I put together a basic little script to add the missing procedurals. To do this, I had to learn how to:
- Read and write ASS files
- Iterate over nodes and find a specific type of node
- Get parameter values from a node
- Create new nodes
from arnold import * import glob ass_file = "Hair_Archive.ass" AiBegin() AiMsgSetConsoleFlags(AI_LOG_ALL) AiASSLoad(ass_file, AI_NODE_ALL) # Iterate over all shape nodes, which includes procedural nodes iter = AiUniverseGetNodeIterator(AI_NODE_SHAPE); while not AiNodeIteratorFinished(iter): node = AiNodeIteratorGetNext(iter) #print AiNodeGetName( node ) # Is the node a procedural? if AiNodeIs( node, "procedural" ): data = AiNodeGetStr( node, "data" ) name = AiNodeGetStr( node, "name" ) # Find all other chunk.<chunk-number>.<frame>.bin files chunks = glob.glob( data.replace( 'chunk.0', 'chunk.*' ) ) # Add procedural nodes for chunks 1,2,3... for i in range(1,len(chunks)): n = AiNode("procedural"); AiNodeSetStr(n, "name", "%s.%s" % (name, i) ) AiNodeSetStr(n, "dso", "sitoa_curves_proc.dll") AiNodeSetStr(n, "data", data.replace( 'chunk.0', 'chunk.%s' % i ) ) AiNodeSetBool(n, "load_at_init", True) AiNodeIteratorDestroy(iter) AiASSWrite(ass_file, AI_NODE_ALL, False) AiEnd()
thank god for the python api, i have done numerous tasks with it and it has really saved my bacon!
How i can read output filename from driver_exr section in ASS file with Arnold Python API?
this method is correct?
def getOutputFileName(ass_file):
filename = None
AiBegin()
AiMsgSetConsoleFlags(AI_LOG_ALL)
AiASSLoad(ass_file, AI_NODE_DRIVER)
iter = AiUniverseGetNodeIterator(AI_NODE_DRIVER)
while not AiNodeIteratorFinished(iter):
node = AiNodeIteratorGetNext(iter)
filename = AiNodeGetStr( node, “filename” )
break
AiNodeIteratorDestroy(iter)
AiEnd()
return filename
Hi a little question, Where can I find documentations for mtoa python api in maya?
I can’t seem to find it at https://support.solidangle.com/category/mtoa nor vie google
Use the docs for the Arnold C++ API. You’ll need to download the Arnold SDK from solidangle.com/arnold/download
There is an error when I use with your method to change .ass file which export in maya.
It cannot find the “MayaFile” node and “MayaShadingEngine” node, it shows :
node “MayaShadingEngine” is not installed,
node “MayaFile” is not installed.
and the new .ass file doesn’t have the node “MayaFile” and node “MayaShadingEngine” and node “standard”.
I need your help!!! thanks very much
In the same way that you have to use kick -l to load the MtoA shaders, you need to use AiLoadPlugins to load the MtoA shaders.
https://arnoldsupport.com/2014/04/16/arnold-loading-plugins-when-you-edit-ass-files/