Autodesk / maya-usd

A common USD (Universal Scene Description) plugin for Autodesk Maya
769 stars 201 forks source link

UsdMayaSchemaApiAdaptor creates empty attributes #2606

Open mrawde opened 2 years ago

mrawde commented 2 years ago

Describe the bug it would be nice if the schema adaptor didn't create attributes that it didn't need to.

When adding an adaptor for MeshLightAPI for PxrMeshLight, we noticed that many attributes end up being created without values.

The schemaAdaptor->GetAttribute(attrName) ends up creating the attribute. But then if attrAdaptor.Get(&value) fails, we end up with an attribute without any value.

Steps to reproduce Here's a script you can run to reproduce the issue

import maya.standalone
maya.standalone.initialize()
import mayaUsd.lib as mayaUsdLib
from maya import cmds
import os

cmds.loadPlugin("mayaUsdPlugin")

class _LightAPIAdaptor(mayaUsdLib.SchemaApiAdaptor):
    def CanAdapt(self):
        return True
    def CanAdaptForExport(self, jobArgs):
        return True

    def GetAdaptedAttributeNames(self):
        return ['inputs:intensity', 'inputs:exposure']

    def GetMayaNameForUsdAttrName(self, usdName):
        mayaName = usdName.split(":")[-1]
        return mayaName

def _AddFloat(shape, name, val):
    cmds.addAttr(shape, longName=name, attributeType='float', defaultValue=val)

def main():
    # Suppose some plugin registers some apiSchemas that could apply to all
    # shapes.
    mayaUsdLib.SchemaApiAdaptor.Register(_LightAPIAdaptor, "shape", "LightAPI")

    # create a mesh to export
    cmds.file(new=True, force=True)
    sphere, _ = cmds.polySphere()
    sphereShape = cmds.listRelatives(sphere, shapes=True)[0]
    _AddFloat(sphereShape, 'intensity', 1.0)
    _AddFloat(sphereShape, 'exposure', 1.0) # note default is 0.0

    outFile = os.path.abspath('./tmp.usda')
    # When exporting a "mesh" (which is also a "shape"), I'd expect both schemas
    # to be exported.
    cmds.mayaUSDExport(file=outFile, apiSchema=["LightAPI"])

    from pxr import Sdf
    layer = Sdf.Layer.FindOrOpen(outFile)
    assert(layer.GetAttributeAtPath('/pSphere1.inputs:exposure'))
    assert(not layer.GetAttributeAtPath('/pSphere1.inputs:intensity'))

if __name__ == '__main__':
    main()

Expected behavior I'd expect the script above to run without getting the assertion error.

The resulting usd looks like

    float inputs:exposure = 1
    float inputs:intensity

I'd expect only inputs:exposure to be present (which is what the assert is testing).

tanant commented 2 years ago

heya @mrawde - seems legit, were you able (or planning) to put a patch in for this one?

mrawde commented 2 years ago

Hey @tanant. I was just filing this as something I noticed when trying to use the UsdMayaSchemaApiAdaptor. I don't have a good idea on how to fix this.