# Using the Python API
# Loading USD files
All the functions exposed by the Multiverse Python API are contained in the
multiverse
module:
import multiverse
To create a new mvUsdCompoundShape node and load an USD asset simply pass the
asset file path to CreateUsdCompound
:
nodeName = multiverse.CreateUsdCompound('/path/to/asset.usdc')
We can also create a new mvUsdCompoundShape node and load multiple USD assets at the same time:
nodeName = multiverse.CreateUsdCompound(
['/path/to/asset.usd', '/path/to/overrides.usd'])
2
To query the paths of set assets currently set on a mvUsdCompoundShape node use:
paths = multiverse.GetUsdCompoundAssetPaths(nodeName)
# paths = ['/path/to/asset.usd', '/path/to/overrides.usd']
2
3
# Writing USD files
Multiverse API functions to write USD files support different set of options
that can be passed to control the export operations. Since each write function
can support a fairly large number of options, these are defined by custom
option classes. For example, in order to export a Maya mesh object to USD,
we can choose if we want to export normals, uvs, etc... For assets, all of
these options are made available through the AssetWriteOptions
class.
For example to export a mesh sphere object called pSphere1
enabling normals
and UVs information we would use:
opts = multiverse.AssetWriteOptions()
opts.writeNormals = True
opts.writeUVs = True
multiverse.WriteAsset('/path/to/sphere.usd', 'pSphere1', opts)
2
3
4
5
6
This also allows for options to be shared across different export operations.
Classes to control writing of assets and compositions (AssetWriteOptions
and
CompositionWriteOptions
) also support a sub-set of options for animation.
These options can be specified once the option object has been created or
passed as parameter to the constructor (for example to share the same settings
when writing assets and compositions):
# Case 1 - time options are set directly after object creation.
opts = multiverse.AssetWriteOptions()
opts.writeNormals = True
opts.writeUVs = True
opts.timeOptions.writeTimeRange = True
opts.timeOptions.frameRange = (1, 10)
# Case 2 - time options are passed as parameter to the constructor.
timeOpts = multiverse.TimeOptions()
timeOpts.writeTimeRange = True
timeOpts.frameRange = (1, 10)
assetOpts = multiverse.AssetWriteOptions(timeOptions=timeOpts)
compositionOpts = multiverse.CompositionWriteOptions(timeOptions=timeOpts)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Callback for Writing
As of version 8.0.1 there is a new writer callback functionality, allowing the TD to execute custom python scripts on USD write. Any functionality available from the USD and Python API can be used, such as removing unwanted prims, adding custom attributes, even notifying databases.
More information can be found in the callbacks section.
# Querying USD hierarchy
To query information about an asset's hierarchy, Multiverse exposes the
GetChildrenForPath
API function. The function takes the name of a
mvUsdCompoundShape node and an item path and returns a list containing the
children for the given item:
import multiverse
children = multiverse.GetChildrenForPath('myUsdCompoundShape', '/main')
2
3
The returned children
list consists of MvUsdItem
objects that contain
information, such as name, parent, full path, for the child items.
child = children[0]
child
# /main/obj1
child.name
# obj1
child.fullPath
# /main/obj1
child.parent
# /main
child.typeName
# Xform
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
The GetChildrenForPath
API function can be used to easily traverse the full
hierarchy for an asset:
import os
def TraverseHierarchy(nodeName, root, depth=0):
children = multiverse.GetChildrenForPath(nodeName, root)
for child in children:
print('{}- {} -- {}'.format(' ' * depth , child.name, child.fullPath))
TraverseHierarchy(nodeName, os.path.join(root, child.name), depth + 1)
TraverseHierarchy('croc_animShape', '/')
# - main -- /main
# - obj1 -- /main/obj1
# - part1 -- /main/obj1/part1
# - part2 -- /main/obj1/part2
# - obj2 -- /main/obj2
# - part1 -- /main/obj2/part1
# ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Authoring Overrides
Multiverse API functions to author USD overrides provide a set of operations
that can be used to create, query, remove/reset and writing. For example, we
can read a USD asset called ashtray_geo.usdc
and afterwards we can do series
of operations from creating override, writing the override, getting the
information and even remove the overrides.
Let's start defining the basic codes so that we can use them for the rest of the example:
import multiverse
from pymel import core as pmc
# Ashtray geo USD asset.
ashtrayGeoPath = 'ashtray_geo.usdc'
# CreateMat returns shading group Lambert2SG.
sg = CreateMat('lambert')
# Create an mvSet attribute node and set its namespace.
mvSet = pmc.createNode('mvSet')
mvSet.materialNamespace.set('fakeNameSpace')
xFormPrimPath = '/Ashtray/geo_cigaretteButt_1'
matPrimPath = '/Ashtray/geo_ashtray'
attrPath = '/Ashtray'
visPath = '/Ashtray/geo_cigarette'
# Read the asset.
mvNode = multiverse.CreateUsdCompound(ashtrayGeoPath)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Since now we have read the ashtray_geo.usdc
into mvNode
we can start using
the Multiverse API functions to author the overrides. Let's start by creating
different types of override:
# Create transform override to move '/Ashtray/geo_cigaretteButt_1' two
# units in 'x'.
xform = multiverse.CreateTransformOverride(mvNode, xFormPrimPath)
pmc.move(xform, (2, 0, 0))
# Create material override for '/Ashtray/geo_ashtray'.
multiverse.AddMaterialOverride(mvNode, matPrimPath, sg)
# Create attribute set override for '/Ashtray'.
multiverse.AddAttributeSetOverride(mvNode, attrPath, mvSet.name())
# Create viewport visibility override for '/Ashtray/geo_cigarette' to hidden.
multiverse.SetViewportVisibility(mvNode, visPath,
multiverse.VisibilityMode.HIDDEN)
# Create render visibility override for '/Ashtray/geo_cigarette' to hidden.
multiverse.SetRenderVisibility(mvNode, visPath,
multiverse.VisibilityMode.HIDDEN)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Now that we have covered the writing functions, let's have a look at the snippets below to check for different kind of overrides:
# Check for transform override.
multiverse.HasTransformOverride(mvNode, xFormPrimPath)
# Check for material override.
multiverse.HasMaterialOverride(mvNode, matPrimPath)
# Check for attribute override.
multiverse.HasAttributeOverride(mvNode, attrPath)
# Check for viewport visibility override.
multiverse.HasViewportVisibilityOverride(mvNode, visPath)
# Check render visibility override.
multiverse.HasRenderVisibilityOverride(mvNode, visPath)
2
3
4
5
6
7
8
9
10
11
12
13
14
We can also remove specific overrides that we have done:
# Remove transform override.
multiverse.RemoveTransformOverride(mvNode, xFormPrimPath)
# Remove material override.
multiverse.RemoveMaterialOverride(mvNode, matPrimPath)
# Remove attribute override.
multiverse.RemoveAttributeSetOverride(mvNode, attrPath)
# Reset viewport visibility.
multiverse.ResetViewportVisibility(mvNode, visPath)
# Reset render visibility.
multiverse.ResetRenderVisibility(mvNode, visPath)
2
3
4
5
6
7
8
9
10
11
12
13
14
If you feel that you want to wipe out per primitive path overrides:
# Get primitives with overrides.
primPaths = multiverse.GetPrimitivesWithOverrides(mvNode)
# Iterate and remove overrides from each primitive in primPaths.
for primPath in primPaths:
multiverse.RemovePrimitiveOverrides(mvNode, primPath)
2
3
4
5
6
You can also remove all overrides for the whole node:
# remove all overrides from the node
multiverse.RemoveNodeOverrides(mvNode)
2
Finally to write the overrides:
ashtrayOverridePath = 'ashtray_over.usda'
overrideOptions = multiverse.OverridesWriteOptions()
overrideOptions.writeVariants = False
multiverse.WriteOverrides(ashtrayOverridePath, mvNode, overrideOptions)
```## Selection Basics
Multiverse API provides two functions to cover selection operations for
`mvUsdCompoundShape`.
Here's a simple snippet to select primitives and query the selection back for
further manipulations:
```python
import multiverse
path = 'ashtray_geo.usdc'
primPaths = ['/Ashtray/geo_cigaretteButt_1', '/Ashtray/geo_ashtray']
# Read the asset.
mvNode = multiverse.CreateUsdCompound(path)
# Select primitives.
multiverse.SelectPrimitives(mvNode, primPaths)
# List currently selected primitives.
selectedPrims = multiverse.GetSelectedPrimitives(mvNode)
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
# Writing USD Compositions
Multiverse API to write a composition has similar flow as WriteAsset
.
By specifying the path where the composition will be written, selection of Maya
nodes and the options that can be customized by declaring each options
separately.
Here is a simple snippet to read two USD files, layer them together, make it as a group and write it as a USD composition:
import multiverse
from pymel import core as pmc
baseAshtray = 'ashtray_geo.usdc'
overAshtray = 'ashtray_over.usda'
# Read and layer the overrides.
assetPaths = [baseAshtray, overAshtray]
mvNode = multiverse.CreateUsdCompound(assetPaths)
# Get the transform node from mvNode.
mvNodeXForm = pmc.listRelatives(mvNode, allParents=True)[0].name()
# Put the USD under Ashtray group
rootGrp = pmc.group(mvNodeXForm, name='Ashtray')
# Set composition options.
timeOptions = multiverse.TimeOptions()
compOptions = multiverse.CompositionWriteOptions(timeOptions=timeOptions)
# Write composition.
output = 'AshtrayFinal.usda'
multiverse.WriteComposition(output, rootGrp.name(), compOptions)
# Read back the result.
asset = multiverse.CreateUsdCompound(output)
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
# Writing Animations
In order to write animation, we can specify the path and selection of objects
that we want to write the animations. Make sure to set the necessary animation
properties by using AssetWriteOptions
and pass the option to WriteAsset
:
import multiverse
path = 'croc_anim.usdc'
selections = ['crocGeo_grp', 'necklace']
# Set write animation options.
writeOptions = multiverse.AssetWriteOptions()
writeOptions.timeOptions.writeTimeRange = True
writeOptions.timeOptions.frameRange = (1, 64)
# Write the animation.
multiverse.WriteAsset(path, selections, writeOptions)
# Read it back.
mvNode = multiverse.CreateUsdCompound(path)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Setting Variant Overrides
Multiverse API offers a set of functions to author variant overrides. Here is a
simple snippet to set, reset and querying overrides from a mvUsdCompoundShape
:
import multiverse
assetPath = 'sphere_variant.usda'
primPath = '/Sphere'
# Read the USD.
mvNode = multiverse.CreateUsdCompound(assetPath)
# Get the variants. Result will be {'shadingVariant': ('green', ['blue', 'green', 'red'])}.
# If contains more variants, the key of the dictionary will have the same format.
variants = multiverse.GetVariantSetsData(mvNode, primPath)
# Get the variant name. Result: 'shadingVariant'
variantName = variants.keys()[0]
# Get the variant values. Result: ['blue', 'green', 'red']
variantValues = variants[variantName][-1]
# Set the variant to 'red'.
multiverse.SetVariantSetsOverride(mvNode, primPath, variantName, variantValues[2])
# Check whether mvNode has Variants
multiverse.HasVariantsOverride(mvNode, primPath)
# Reset 'shadingVariant'
multiverse.ResetVariantOverride(mvNode, primPath, variantName)
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