Metadata
USD allows us to extend the base metadata that is attached to every layer, prim and property (Supported are Sdf.Layer
and subclasses of Sdf.Spec
). This allows us to write custom fields with a specific type, so that we don't have to rely on writing everything into the assetInfo
and customData
entries.
To get an overview of metadata in USD, check out our dedicated metadata section.
Table of Contents
TL;DR - Metadata Plugins In-A-Nutshell
- Extending USD with custom metadata fields is as simple as creating a
plugInfo.json
file with entires for what custom fields you want and on what entities (Supported areSdf.Layer
and subclasses ofSdf.Spec
).
What should I use it for?
In production, most of the sidecar metadata should be tracked via the assetInfo
and customData
metadata entries. It does make sense to extend the functionality with own metadata keys for:
- Doing high performance lookups. Metadata is fast to read, as it follows simpler composition rules, so we can use it as a
IsA
replacement mechanism we can tag our prims/properties with. - We can add list editable ops metadata fields, this can be used as a way to layer together different array sidecar data. For an example see our Reading/Writing the installed custom metadata section.
Resources
Overview
Here is the minimal plugin template with all options you can configure for your metadata:
{
"Plugins": [
{
"Name": "<PluginName>",
"Type": "resource",
"Info": {
"SdfMetadata": {
"<field_name>" : {
"appliesTo": "<Optional comma-separated list of spec types this field applies to>",
"default": "<Optional default value for field>",
"displayGroup": "<Optional name of associated display group>",
"type": "<Required name indicating field type>",
}
}
}
}
]
}
We can limit the metadata entry to the following Sdf.Layer
/Subclasses of Sdf.Spec
s with the type
entry:
"appliesTo" token | Spec type |
---|---|
layers | SdfLayer (SdfPseudoRootSpec) |
prims | SdfPrimSpec, SdfVariantSpec |
properties | SdfPropertySpec |
attributes | SdfAttributeSpec |
relationships | SdfRelationshipSpec |
variants | SdfVariantSpec |
You can find all the supported data types on this page in the official docs: USD Cookbook - Extending Metadata.
Installing a metadata plugin
Here is an example plugInfo.json
file for metadata, it also ships with this repo here.
{
"Plugins": [
{
"Name": "usdSurvivalGuideMetadata",
"Type": "resource",
"Info": {
"SdfMetadata": {
"usdSurvivalGuideOverrideTimeCode": {
"type": "double[]",
"appliesTo": "layers",
"default": [1001.0, 1050.0]
},
"usdSurvivalGuideFloat": {
"type": "double",
"appliesTo": "prims",
"default": 5
},
"usdSurvivalGuideAssetDependencies": {
"type": "stringlistop",
"appliesTo": "prims"
}
}
}
}
]
}
To register the above metadata plugin, copy the contents into a file called plugInfo.json
. Then set your PXR_PLUGINPATH_NAME
environment variable to the folder containing the plugInfo.json
file.
For Linux this can be done for the active shell as follows:
export PXR_PLUGINPATH_NAME=/my/cool/plugin/resources:${PXR_PLUGINPATH_NAME}
If you downloaded this repo, we provide the above example metadata plugin here. All you need to do is point the environment variable there and launch a USD capable application.
Reading/Writing the installed custom metadata
Once the plugin is loaded, we can now read and write to the custom entry.
Custom metadata fields on the Sdf.Layer
are not exposed via Python (as far as we could find).
from pxr import Usd, Sdf
# Here we test it in an example stage:
stage = Usd.Stage.CreateInMemory()
layer = stage.GetEditTarget().GetLayer()
prim = stage.DefinePrim("/prim")
prim_spec = layer.GetPrimAtPath(prim.GetPath())
# To see all the globally registered fields for the metadata on prim specs:
print(Sdf.PrimSpec.GetMetaDataInfoKeys(prim_spec))
# Float field
metadata_name = "usdSurvivalGuideFloat"
print(prim.GetMetadata(metadata_name)) # Returns: None
print(prim_spec.GetFallbackForInfo(metadata_name)) # Returns: 5
prim.SetMetadata(metadata_name, 10)
print(prim.GetMetadata(metadata_name)) # Returns: 10
# String List Editable Op
metadata_name = "usdSurvivalGuideAssetDependencies"
string_list_op = Sdf.StringListOp.Create(appendedItems=["motor.usd", "tire.usd"])
print(prim.GetMetadata(metadata_name))
prim.SetMetadata(metadata_name, string_list_op)
print(prim.GetMetadata(metadata_name))