# Callbacks
# USD Writer Callbacks
When exporting to a USD file, we can have MfM optionally call custom python code over the generated USD file. This allows for custom pipeline steps that can be tailed by each client. Examples can be:
Clean-up "reference" prims - delete from final file any prims that were originally used as a guide for modelling without needing to place them in separate hierarchies.
Notify some back end that a specific asset has been written - this can be a database, a Slack notification, etc.
Within this script, the full functionality of the USD Python API can be used, as well as all standard Python. Processing can be done directly on the USD, on the filepath of where the file is written, or environment variables.
Callback scripts are specified to be executed via the API write commands:
import multiverse as mv
opts = mv.AssetWriteOptions()
opts.customPostCallback = '~/CustomCallback.py'
mv.WriteAsset('~/assets00.usda', ['assetGroup'], opts)
2
3
4
# Clean-up by name
Given the following Maya scene, we want to keep assetGroup/Hero
, but remove
the assetGroup/_ReferenceHero
and assetGroup/TEMP_Mesh
:
The following script "cleans up" the exported USD file according to some regex
pattern matching. This script will live somewhere in your pipeline's path, call
it ~/CleanupByName.py
.
Note
Note the usage of the namespaced Multiverse mvpxr
Python module (instead of
the USD default pxr
one). This ensures a level of protection in case other
Maya plugins that link with different versions of the USD libraries are
concurrently loaded in Maya.
import sys
import mvpxr
import re
PRIM_TRIM_MATCH = ['^_Reference', '^TEMP']
def CollectTrimPrims(stage):
trimPrims = []
for prim in stage.Traverse():
primName = prim.GetName()
for pattern in PRIM_TRIM_MATCH:
if re.search(pattern, primName):
trimPrims.append(prim)
return trimPrims
def main(filePath):
stage = mvpxr.Usd.Stage.Open(filePath)
primsToTrim = CollectTrimPrims(stage)
for prim in primsToTrim:
if prim.IsValid():
print('Removing', prim)
stage.RemovePrim(prim.GetPath())
stage.GetRootLayer().Save()
stage.Unload()
if __name__ == '__main__':
filePath = sys.argv[sys.argv.index('--filePath')+1]
main(filePath)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
The resulting USD will contain the Hero
prim, but not the _Reference*
or
the TEMP*
.
# Adding Scene & Shot Information
If you automatically want to add any properties to any specific prim based on
the filepath, the following script can be used as a starting point. It assumes
that as part of your final filepath, you have the words sceneXX
and shotYY
,
where XX
and YY
are the scene and shot numbers, eg:
/projects/ultra/scene31/shot42/asset77.usda
.
import sys
import mvpxr
import re
def GetPart(pattern, text):
match = re.findall(pattern, text)
if match:
return match[0]
def GetSceneShot(filePath):
scene = GetPart(r'(scene\d+)', filePath)
shot = GetPart(r'(shot\d+)', filePath)
return scene, shot
def main(filePath):
scene, shot = GetSceneShot(filePath)
if scene and shot:
stage = mvpxr.Usd.Stage.Open(filePath)
prim = stage.GetDefaultPrim()
prim.CreateAttribute('scene', Sdf.ValueTypeNames.String).Set(scene)
prim.CreateAttribute('shot', Sdf.ValueTypeNames.String).Set(shot)
stage.GetRootLayer().Save()
stage.Unload()
if __name__ == '__main__':
filePath = sys.argv[sys.argv.index('--filePath')+1]
main(filePath)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
The resulting USD file will have properties scene31
and shot42
added to the
default prim.