Beispiel #1
0
 def getRegistry(cls):
     if cls._reg is None:
         try:
             cls._reg = Sdr.Registry()
         except:
             pass
     return cls._reg
Beispiel #2
0
    def test_Registry(self):
        """
        Test basic registry operations. Also ensures that the discovery process
        works correctly.
        """

        # Register test plugins and verify they have been found
        pr = Plug.Registry()
        plugins = pr.RegisterPlugins(testPluginsDsoSearch)

        # Verify the test plugins have been found.  When building monolithic
        # we should find at least these derived types.
        self.assertEqual(len(plugins), 1)
        fsdpType = Tf.Type.FindByName('_NdrFilesystemDiscoveryPlugin')
        tdpType = Tf.Type.FindByName('_NdrTestDiscoveryPlugin')
        self.assertEqual(
            set([fsdpType, tdpType]) -
            set(pr.GetAllDerivedTypes('NdrDiscoveryPlugin')), set())
        self.assertEqual(
            set([
                Tf.Type.FindByName('_NdrArgsTestParserPlugin'),
                Tf.Type.FindByName('_NdrOslTestParserPlugin')
            ]) - set(pr.GetAllDerivedTypes('NdrParserPlugin')), set())

        # Instantiating the registry will kick off the discovery process.
        # This test assumes the PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY has
        # been set prior to being run to ensure built-in plugins are not
        # found. Instead we'll list the plugins we want explicitly.

        # Setting this from within the script does not work on Windows.
        # os.environ["PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY"] = ""
        reg = Sdr.Registry()
        reg.SetExtraDiscoveryPlugins([fsdpType, tdpType])

        nodes = reg.GetShaderNodesByFamily()
        assert len(nodes) == 4
        assert reg.GetSearchURIs() == ["/TestSearchPath"]
        assert set(reg.GetNodeNames()) == {
            "TestNodeARGS", "TestNodeOSL", "TestNodeSameName"
        }
        assert id(reg.GetShaderNodeByURI(nodes[0].GetSourceURI())) == id(
            nodes[0])
        assert id(reg.GetShaderNodeByName(nodes[0].GetName())) == id(nodes[0])

        argsType = "RmanCpp"
        oslType = "OSL"

        # Ensure that the registry can retrieve two nodes of the same name but
        # different source types
        assert {argsType, oslType}.issubset(set(reg.GetAllNodeSourceTypes()))
        assert len(reg.GetShaderNodesByName("TestNodeSameName")) == 2
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              oslType) is not None
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              argsType) is not None
        assert reg.GetShaderNodeByName("TestNodeSameName", [oslType, argsType])\
                  .GetSourceType() == oslType
        assert reg.GetShaderNodeByName("TestNodeSameName", [argsType, oslType])\
                  .GetSourceType() == argsType
Beispiel #3
0
    def setUpClass(cls):
        """
        Load the test modules for discovery and parsing and check basic type
        registration
        """

        # Register test plugins and verify they have been found
        cls.pr = Plug.Registry()
        plugins = cls.pr.RegisterPlugins(testPluginsDsoSearch)

        # Verify the test plugins have been found.  When building monolithic
        # we should find at least these derived types.
        assert len(plugins) == 1
        cls.tdpType = Tf.Type.FindByName('_NdrTestDiscoveryPlugin')
        cls.tdp2Type = Tf.Type.FindByName('_NdrTestDiscoveryPlugin2')

        cls.tppType = Tf.Type.FindByName('_NdrArgsTestParserPlugin')
        cls.tpp2Type = Tf.Type.FindByName('_NdrOslTestParserPlugin')

        # We don't check for all the derived types of NdrDiscoveryPlugin
        # because this test only uses the discovery and parser plugins
        # that are defined in this testenv
        assert {cls.tdpType, cls.tdp2Type}.issubset(
            set(cls.pr.GetAllDerivedTypes('NdrDiscoveryPlugin')))
        assert {cls.tppType, cls.tpp2Type
                }.issubset(set(cls.pr.GetAllDerivedTypes('NdrParserPlugin')))

        # Instantiating the registry will kick off the discovery process.
        # This test assumes the PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY
        # and PXR_NDR_SKIP_PARSER_PLUGIN_DISCOVERY has been set prior to
        # being run to ensure built-in plugins are not found. Instead
        # we'll list the plugins we want explicitly.

        # Setting this from within the script does not work on Windows.
        # os.environ["PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY"] = ""
        # os.environ["PXR_NDR_SKIP_PARSER_PLUGIN_DISCOVERY"] = ""
        cls.reg = Sdr.Registry()

        # Set up the test parser plugins.
        cls.reg.SetExtraParserPlugins([cls.tppType, cls.tpp2Type])

        # We will register the discovery plugins one by one so that we can check
        # source types are not duplicated in the registry if we have plugins
        # that discover nodes of the same source type

        # The _NdrTestDiscoveryPlugin should find discovery results that have
        # source types of RmanCpp and OSL
        cls.reg.SetExtraDiscoveryPlugins([cls.tdpType])
        assert sorted(cls.reg.GetAllNodeSourceTypes()) == \
            [cls.oslType, cls.argsType]

        # The _NdrTestDiscoveryPlugin2 should find discovery results that have
        # source types of RmanCpp and glslfx
        cls.reg.SetExtraDiscoveryPlugins([cls.tdp2Type])
Beispiel #4
0
    def test_Registry(self):
        """
        Test basic registry operations. Also ensures that the discovery process
        works correctly.
        """

        # Register test plugins and verify they have been found
        pr = Plug.Registry()
        plugins = pr.RegisterPlugins(testPluginsDsoSearch)

        self.assertEqual(len(plugins), 1)
        self.assertEqual(
            set(pr.GetAllDerivedTypes('NdrDiscoveryPlugin')),
            set([
                Tf.Type.FindByName('_NdrFilesystemDiscoveryPlugin'),
                Tf.Type.FindByName('_NdrTestDiscoveryPlugin')
            ]))
        self.assertEqual(
            set(pr.GetAllDerivedTypes('NdrParserPlugin')),
            set([
                Tf.Type.FindByName('_NdrArgsTestParserPlugin'),
                Tf.Type.FindByName('_NdrOslTestParserPlugin')
            ]))

        # Instantiating the registry will kick off the discovery process
        reg = Sdr.Registry()
        nodes = reg.GetShaderNodesByFamily()

        assert len(nodes) == 4
        assert reg.GetSearchURIs() == ["/TestSearchPath"]
        assert set(reg.GetNodeNames()) == {
            "TestNodeARGS", "TestNodeOSL", "TestNodeSameName"
        }
        assert id(reg.GetShaderNodeByURI(nodes[0].GetSourceURI())) == id(
            nodes[0])
        assert id(reg.GetShaderNodeByName(nodes[0].GetName())) == id(nodes[0])

        argsType = "RmanCpp"
        oslType = "OSL"

        # Ensure that the registry can retrieve two nodes of the same name but
        # different source types
        assert {argsType, oslType}.issubset(set(reg.GetAllNodeSourceTypes()))
        assert len(reg.GetShaderNodesByName("TestNodeSameName")) == 2
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              oslType) is not None
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              argsType) is not None
        assert reg.GetShaderNodeByName("TestNodeSameName", [oslType, argsType])\
                  .GetSourceType() == oslType
        assert reg.GetShaderNodeByName("TestNodeSameName", [argsType, oslType])\
                  .GetSourceType() == argsType
Beispiel #5
0
    def test_Basic(self):
        r = Sdr.Registry()

        uvTextureNode = r.GetNodeByName('UsdUVTexture', ['OSL'])
        self.assertTrue(uvTextureNode)
        self.assertEqual(
            uvTextureNode.GetInputNames(),
            ['file', 'st', 'wrapS', 'wrapT', 'fallback', 'scale', 'bias'])

        primvarReaderNode = r.GetNodeByName('UsdPrimvarReader_float', ['OSL'])
        self.assertTrue(primvarReaderNode)
        self.assertEqual(primvarReaderNode.GetInputNames(),
                         ['varname', 'fallback'])
Beispiel #6
0
    def test_NodeParser(self):
        """
        Test MaterialX node parser.
        """
        # Let the plugin discover our nodes.
        searchPath = os.getcwd()
        os.environ['PXR_USDMTLX_PLUGIN_SEARCH_PATHS'] = searchPath

        # Find our nodes.
        nodes = Sdr.Registry().GetShaderNodesByFamily('UsdMtlxTestNode')
        self.assertEqual(sorted([node.GetName() for node in nodes]), [
            'nd_boolean',
            'nd_customtype',
            'nd_float',
            'nd_integer',
            'nd_string',
            'nd_surface',
            'nd_vector',
        ])

        # Verify common info.
        for node in nodes:
            self.assertEqual(node.GetSourceType(), "OSL")
            self.assertEqual(node.GetFamily(), "UsdMtlxTestNode")
            self.assertEqual(sorted(node.GetInputNames()), ["in", "note"])
            if node.GetName() == 'nd_surface':
                # XXX -- Should shader semantic nodes have a named output?
                self.assertEqual(node.GetOutputNames(), [])
            else:
                self.assertEqual(node.GetOutputNames(), ["result"])

        # Verify converted types.
        typeNameMap = {
            'boolean': 'bool',
            'customtype': 'customtype',
            'float': 'float',
            'integer': 'int',
            'string': 'string',
            'surface': 'string',
            'vector': 'vector',
        }
        for node in nodes:
            # Strip leading nd_ from name.
            name = node.GetName()[3:]

            # Get the input.
            prop = node.GetInput('in')

            # Verify type.
            self.assertEqual(prop.GetType(), typeNameMap.get(name))
Beispiel #7
0
    def test_GetShaderNodeFromAsset(self):
        """
        Test that invoking the parser to identify shader definitions from an
        asset file works when specifying a subIdentifier and sourceType
        """
        reg = Sdr.Registry()

        node = reg.GetShaderNodeFromAsset(
            "shaderDefs.usda",  # shaderAsset
            {},  # metadata
            "TestShaderPropertiesNodeUSD",  # subIdentifier
            "glslfx"  # sourceType
        )

        assert node is not None
        assert node.GetIdentifier().endswith(
            "<TestShaderPropertiesNodeUSD><glslfx>")
Beispiel #8
0
    def test_NodeParser(self):
        """
        Test MaterialX node parser.
        """
        # Find our nodes.
        nodes = Sdr.Registry().GetShaderNodesByFamily('UsdMtlxTestNode')
        self.assertEqual(sorted([node.GetName() for node in nodes]), [
            'UsdMtlxTestNamespace:nd_boolean',
            'UsdMtlxTestNamespace:nd_customtype',
            'UsdMtlxTestNamespace:nd_float',
            'UsdMtlxTestNamespace:nd_integer',
            'UsdMtlxTestNamespace:nd_string',
            'UsdMtlxTestNamespace:nd_surface',
            'UsdMtlxTestNamespace:nd_vector',
        ])

        # Verify common info.
        for node in nodes:
            implementationUri = node.GetResolvedImplementationURI()
            self.assertEqual(os.path.normcase(implementationUri),
                             os.path.normcase(os.path.abspath("test.mtlx")))
            self.assertEqual(node.GetSourceType(), "mtlx")
            self.assertEqual(node.GetFamily(), "UsdMtlxTestNode")
            self.assertEqual(sorted(node.GetInputNames()), ["in", "note"])
            self.assertEqual(node.GetOutputNames(), ['out'])

        # Verify converted types.
        typeNameMap = {
            'boolean': 'bool',
            'customtype': 'customtype',
            'float': 'float',
            'integer': 'int',
            'string': 'string',
            'surface': 'string',
            'vector': 'float',  # vector actually becomes a float[3], but the
            # array size is not represented in the Type
        }
        for node in nodes:
            # Strip leading UsdMtlxTestNamespace:nd_ from name.
            name = node.GetName()[24:]

            # Get the input.
            prop = node.GetInput('in')

            # Verify type.
            self.assertEqual(prop.GetType(), typeNameMap.get(name))
Beispiel #9
0
 def getRegistry(cls):
     if cls._reg is None:
         cls._reg = Sdr.Registry()
     return cls._reg
Beispiel #10
0
    def test_Registry(self):
        """
        Test basic registry operations. Also ensures that the discovery process
        works correctly.
        """

        # Register test plugins and verify they have been found
        pr = Plug.Registry()
        plugins = pr.RegisterPlugins(testPluginsDsoSearch)

        # Verify the test plugins have been found.  When building monolithic
        # we should find at least these derived types.
        self.assertEqual(len(plugins), 1)
        tdpType = Tf.Type.FindByName('_NdrTestDiscoveryPlugin')
        tdp2Type = Tf.Type.FindByName('_NdrTestDiscoveryPlugin2')

        tppType = Tf.Type.FindByName('_NdrArgsTestParserPlugin')
        tpp2Type = Tf.Type.FindByName('_NdrOslTestParserPlugin')

        # We don't check for all the derived types of NdrDiscoveryPlugin
        # because this test only uses the discovery and parser plugins
        # that are defined in this testenv
        assert {tdpType, tdp2Type
                }.issubset(set(pr.GetAllDerivedTypes('NdrDiscoveryPlugin')))
        assert {tppType, tpp2Type
                }.issubset(set(pr.GetAllDerivedTypes('NdrParserPlugin')))

        # The following source types are what we expect to discover from
        # _NdrTestDiscoveryPlugin and _NdrTestDiscoveryPlugin2.  Note that there
        # is no glslfx parser plugin provided in this test.
        argsType = "RmanCpp"
        oslType = "OSL"
        glslfxType = "glslfx"

        # Instantiating the registry will kick off the discovery process.
        # This test assumes the PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY
        # and PXR_NDR_SKIP_PARSER_PLUGIN_DISCOVERY has been set prior to
        # being run to ensure built-in plugins are not found. Instead
        # we'll list the plugins we want explicitly.

        # Setting this from within the script does not work on Windows.
        # os.environ["PXR_NDR_SKIP_DISCOVERY_PLUGIN_DISCOVERY"] = ""
        # os.environ["PXR_NDR_SKIP_PARSER_PLUGIN_DISCOVERY"] = ""
        reg = Sdr.Registry()

        # Set up the test parser plugins.
        reg.SetExtraParserPlugins([tppType, tpp2Type])

        # We will register the discovery plugins one by one so that we can check
        # source types are not duplicated in the registry if we have plugins
        # that discover nodes of the same source type

        # The _NdrTestDiscoveryPlugin should find discovery results that have
        # source types of RmanCpp and OSL
        reg.SetExtraDiscoveryPlugins([tdpType])
        assert reg.GetAllNodeSourceTypes() == [oslType, argsType]

        # The _NdrTestDiscoveryPlugin2 should find discovery results that have
        # source types of RmanCpp and glslfx
        reg.SetExtraDiscoveryPlugins([tdp2Type])

        # Test that the registry does not see 'RmanCpp' twice as a source type,
        # and that it finds 'glslfx' as a source type
        assert reg.GetAllNodeSourceTypes() == [oslType, argsType, glslfxType]

        # Calling SdrRegistry::GetShaderNodesByFamily() will actually parse the
        # discovery results.
        # Notice that in the five node names we find, we get 'TestNodeSameName'
        # twice because there are two nodes with different source types that
        # have the same name.
        # Notice that we do not see 'TestNodeGLSLFX' because we don't have a
        # parser plugin to support it
        nodes = reg.GetShaderNodesByFamily()
        shaderNodeNames = [node.GetName() for node in nodes]
        assert set(shaderNodeNames) == {
            "TestNodeARGS", "TestNodeARGS2", "TestNodeOSL", "TestNodeSameName",
            "TestNodeSameName"
        }

        assert reg.GetSearchURIs() == ["/TestSearchPath", "/TestSearchPath2"]

        # Calling SdrRegistry::GetNodeNames only looks at discovery results
        # without parsing them.
        # Notice that we get 'TestNodeSameName' only once because we only show
        # unique names.
        # Notice that we see 'TestNodeGLSLFX' because it is in our discovery
        # results even though we do not have a parser plugin that supports its
        # source type.
        assert set(reg.GetNodeNames()) == {
            "TestNodeARGS", "TestNodeARGS2", "TestNodeOSL", "TestNodeSameName",
            "TestNodeGLSLFX"
        }

        assert id(reg.GetShaderNodeByName(nodes[0].GetName())) == id(nodes[0])

        # Ensure that the registry can retrieve two nodes of the same name but
        # different source types
        assert len(reg.GetShaderNodesByName("TestNodeSameName")) == 2
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              oslType) is not None
        assert reg.GetShaderNodeByNameAndType("TestNodeSameName",
                                              argsType) is not None
        assert reg.GetShaderNodeByName("TestNodeSameName", [oslType, argsType])\
                  .GetSourceType() == oslType
        assert reg.GetShaderNodeByName("TestNodeSameName", [argsType, oslType])\
                  .GetSourceType() == argsType

        # Test GetShaderNodeFromAsset to check that a subidentifier is part of
        # the node's identifier if one is specified
        node = reg.GetShaderNodeFromAsset(
            Sdf.AssetPath('TestNodeSourceAsset.oso'),  # shaderAsset
            {},  # metadata
            "mySubIdentifier")  # subIdentifier
        assert node.GetIdentifier().endswith("<mySubIdentifier><>")

        # Test GetShaderNodeFromAsset to check that a sourceType is part of
        # the node's identifier if one is specified
        node = reg.GetShaderNodeFromAsset(
            Sdf.AssetPath('TestNodeSourceAsset.oso'),  # shaderAsset
            {},  # metadata
            "mySubIdentifier",  # subIdentifier
            "OSL")  # sourceType
        assert node.GetIdentifier().endswith("<mySubIdentifier><OSL>")
Beispiel #11
0
    # Note that for nodes with explicit asset paths, this list stores a tuple,
    # with first entry being the sdrNode and second the true identifier
    # (identified from the file basename, which should match the node identifier
    # when queries using GetShaderNodeByIdentifierAndType at runtime).
    sdrNodesToParse = []
    renderContext = ""

    sdrNodesDict = config.get(SchemaConfigConstants.SDR_NODES)
    if sdrNodesDict:
        # Extract any renderContext from the config if specified.
        if SchemaConfigConstants.RENDER_CONTEXT in sdrNodesDict.keys():
            renderContext = \
                    sdrNodesDict.get(SchemaConfigConstants.RENDER_CONTEXT)

        # Extract sdrNodes from the config
        sdrRegistry = Sdr.Registry()
        for sourceType in sdrNodesDict.keys():
            if sourceType == SchemaConfigConstants.RENDER_CONTEXT:
                continue
            if sourceType == SchemaConfigConstants.SOURCE_ASSET_NODES:
                # process sdrNodes provided by explicit sourceAssetNodes
                for assetPath in \
                    sdrNodesDict.get(SchemaConfigConstants.SOURCE_ASSET_NODES):
                    node = Sdr.Registry().GetShaderNodeFromAsset(assetPath)
                    nodeIdentifier = \
                        os.path.splitext(os.path.basename(assetPath))[0]
                    if node:
                        sdrNodesToParse.append((node, nodeIdentifier))
                    else:
                        Tf.Warn("Node not found at path: %s." % (assetPath))
                continue
Beispiel #12
0
    # Parse json config to extract sdrNodes and schema sublayers
    try:
        with open(schemaConfig) as json_file:
            config = json.load(json_file)
    except ValueError as ve:
        Tf.RaiseRuntimeError("Error loading (%s), value error: (%s)" \
                %(schemaConfig, ve))

    if not isinstance(config, dict):
        Tf.Warn("Invalid json config provided, expecting a dictionary")
        sys.exit(1)

    sdrNodesToParse = []

    if config.has_key("sdrNodes"):
        sdrRegistry = Sdr.Registry()
        for sourceType in config['sdrNodes'].keys():
            for nodeId in config['sdrNodes'][sourceType]:
                node = sdrRegistry.GetShaderNodeByNameAndType(
                    nodeId, sourceType)
                if node:
                    sdrNodesToParse.append(node)
                else:
                    Tf.Warn("Invalid Node (%s:%s) provided." %
                            (sourceType, nodeId))
    else:
        Tf.Warn("No sdr nodes provided to generate a schema.usda")
        sys.exit(1)

    if not sdrNodesToParse:
        Tf.Warn("No valid sdr nodes provided to generate a schema.usda")
Beispiel #13
0
def UpdateSchemaWithSdrNode(schemaLayer, sdrNode):
    """
    Updates the given schemaLayer with primSpec and propertySpecs from sdrNode
    metadata. It consume the following attributes (that manifest as Sdr 
    metadata) in addition to many of the standard Sdr metadata
    specified and parsed (via its parser plugin).

    Node Level Metadata:
        - "schemaName": Name of the new schema populated from the given sdrNode
          (Required)
        - "schemaKind": Specifies the UsdSchemaKind for the schema being
          populated from the sdrNode. (note that this does not support
          multi-applied schema kinds).
        - "schemaBase": Base schema from which the new schema should inherit
          from. Note this defaults to "APISchemaBase" for an api schema or 
          "Typed" for a concrete scheme.
        - "usdSchemaClass": Specified the equivalent schema directly generated
          by USD (sourceType: USD). This is used to make sure duplicate
          properties already specified in the USD schema are not populated in
          the new API schema. Note this is only used when we are dealing with an
          API schema.
        - "apiSchemaAutoApplyTo": The Schemas to which the sdrNode populated 
          (API) schema will autoApply to.
        - "tfTypeNameSuffix": Class name which will get registered with TfType 
          system. This gets appended to the domain name to register with TfType.

    Property Level Metadata:
        USD_VARIABILITY = A property level metadata, which specified a specific
        sdrNodeProperty should its usd variability set to Uniform or Varying.
    """
    # Early exit on invalid parameters
    if not schemaLayer:
        Tf.Warn("No Schema Layer provided")
        return
    if not sdrNode:
        Tf.Warn("No valid sdrNode provided")
        return

    sdrNodeMetadata = sdrNode.GetMetadata()

    if not sdrNodeMetadata.has_key(SchemaDefiningKeys.SCHEMA_NAME):
        Tf.Warn("Sdr Node does not define a schema name metadata.")
        return
    schemaName = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_NAME]
    if not Tf.IsValidIdentifier(schemaName):
        Tf.RaiseRuntimeError(
            "schemaName (%s) is an invalid identifier; "
            "Provide a valid USD identifer for schemaName, example (%s) " %
            (schemaName, Tf.MakeValidIdentifier(schemaName)))

    tfTypeNameSuffix = None
    if sdrNodeMetadata.has_key(SchemaDefiningKeys.TF_TYPENAME_SUFFIX):
        tfTypeNameSuffix = sdrNodeMetadata[
            SchemaDefiningKeys.TF_TYPENAME_SUFFIX]
        if not Tf.IsValidIdentifier(tfTypeNameSuffix):
            Tf.RaiseRuntimeError("tfTypeNameSuffix (%s) is an invalid " \
                    "identifier" %(tfTypeNameSuffix))

    if not sdrNodeMetadata.has_key(SchemaDefiningKeys.SCHEMA_KIND):
        schemaKind = SchemaDefiningMiscConstants.TYPED_SCHEMA
    else:
        schemaKind = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_KIND]

    # Note: We are not working on dynamic multiapply schemas right now.
    isAPI = schemaKind == SchemaDefiningMiscConstants.SINGLE_APPLY_SCHEMA
    # Fix schemaName and warn if needed
    if isAPI and \
        not schemaName.endswith(SchemaDefiningMiscConstants.API_STRING):
        Tf.Warn("node metadata implies the generated schema being created is "
                "an API schema, fixing schemaName to reflect that")
        schemaName = schemaName + SchemaDefiningMiscConstants.API_STRING

    if isAPI and tfTypeNameSuffix and \
        not tfTypeNameSuffix.endswith(SchemaDefiningMiscConstants.API_STRING):
        Tf.Warn("node metadata implies the generated schema being created "
                "is an API schema, fixing tfTypeNameSuffix to reflect that")
        tfTypeNameSuffix = tfTypeNameSuffix + \
                SchemaDefiningMiscConstants.API_STRING

    if not sdrNodeMetadata.has_key(SchemaDefiningKeys.SCHEMA_BASE):
        Tf.Warn("No schemaBase specified in node metadata, defaulting to "
                "APISchemaBase for API schemas else Typed")
        schemaBase = SchemaDefiningMiscConstants.API_SCHEMA_BASE if isAPI \
                else SchemaDefiningMiscConstants.TYPED_SCHEMA
    else:
        schemaBase = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_BASE]

    apiSchemaAutoApplyTo = None
    if sdrNodeMetadata.has_key(SchemaDefiningKeys.API_SCHEMA_AUTO_APPLY_TO):
        apiSchemaAutoApplyTo = \
            sdrNodeMetadata[SchemaDefiningKeys.API_SCHEMA_AUTO_APPLY_TO] \
                .split('|')

    usdSchemaClass = None
    if isAPI and sdrNodeMetadata.has_key(SchemaDefiningKeys.USD_SCHEMA_CLASS):
        usdSchemaClass = \
            sdrNodeMetadata[SchemaDefiningKeys.USD_SCHEMA_CLASS]

    primSpec = schemaLayer.GetPrimAtPath(schemaName)

    if (primSpec):
        # if primSpec already exist, remove entirely and recreate using the
        # parsed sdr node
        if primSpec.nameParent:
            del primSpec.nameParent.nameChildren[primSpec.name]
        else:
            del primSpec.nameRoot.nameChildren[primSpec.name]

    primSpec = Sdf.PrimSpec(schemaLayer, schemaName, Sdf.SpecifierClass,
                            "" if isAPI else schemaName)

    primSpec.inheritPathList.explicitItems = ["/" + schemaBase]

    primSpecCustomData = {}
    if isAPI:
        primSpecCustomData["apiSchemaType"] = schemaKind
    if tfTypeNameSuffix:
        # Defines this classname for TfType system
        # can help avoid duplicate prefix with domain and className
        # Tf type system will automatically pick schemaName as tfTypeName if
        # this is not set!
        primSpecCustomData["className"] = tfTypeNameSuffix

    if apiSchemaAutoApplyTo:
        primSpecCustomData['apiSchemaAutoApplyTo'] = \
            Vt.TokenArray(apiSchemaAutoApplyTo)
    primSpec.customData = primSpecCustomData

    doc = sdrNode.GetHelp()
    if doc != "":
        primSpec.documentation = doc

    # gather properties from node directly generated from USD (sourceType: USD)
    # Use the usdSchemaClass tag when the generated schema being defined is an
    # API schema
    usdSchemaNode = None
    if usdSchemaClass:
        reg = Sdr.Registry()
        usdSchemaNode = reg.GetNodeByIdentifierAndType(
            usdSchemaClass, SchemaDefiningMiscConstants.USD_SOURCE_TYPE)

    # Create attrSpecs from input parameters
    for propName in sdrNode.GetInputNames():
        _CreateAttrSpecFromNodeAttribute(primSpec, sdrNode.GetInput(propName),
                                         usdSchemaNode)

    # Create attrSpecs from output parameters
    for propName in sdrNode.GetOutputNames():
        _CreateAttrSpecFromNodeAttribute(primSpec, sdrNode.GetOutput(propName),
                                         usdSchemaNode, False)

    schemaLayer.Save()
Beispiel #14
0
    def test_NodeDiscovery(self):
        """
        Test MaterialX node discovery.
        """
        # Let the plugin discover our nodes.
        searchPath = os.getcwd()
        os.environ['PXR_USDMTLX_PLUGIN_SEARCH_PATHS'] = searchPath

        registry = Sdr.Registry()

        # Check node indentifiers.
        names = sorted(
            registry.GetNodeIdentifiers('UsdMtlxTestNode',
                                        Ndr.VersionFilterAllVersions))
        self.assertEqual(names, [
            'pxr_nd_float', 'pxr_nd_integer', 'pxr_nd_string', 'pxr_nd_vector',
            'pxr_nd_vector_2', 'pxr_nd_vector_2_1', 'pxr_nd_vector_noversion'
        ])

        # Check node names.
        names = sorted(registry.GetNodeNames('UsdMtlxTestNode'))
        self.assertEqual(names, [
            'pxr_nd_float', 'pxr_nd_integer', 'pxr_nd_string', 'pxr_nd_vector'
        ])

        # Get by family.  Non-default versions should be dropped.
        #
        # Because pxr_nd_vector_noversion has no version at all the
        # discovery assumes it's the default version despite appearances
        # to the human eye.
        nodes = registry.GetNodesByFamily('UsdMtlxTestNode')
        names = sorted([node.GetIdentifier() for node in nodes])
        self.assertEqual(names, [
            'pxr_nd_float', 'pxr_nd_integer', 'pxr_nd_string',
            'pxr_nd_vector_2', 'pxr_nd_vector_noversion'
        ])

        # Check all versions.
        # Note that this sorting depends on how unique identifiers are
        # constructed so the order of items on the right hand side of
        # the assertion must stay in sync with that.
        names = sorted([
            name for name in registry.GetNodeIdentifiers(
                filter=Ndr.VersionFilterAllVersions) if name.startswith('pxr_')
        ])
        nodes = [registry.GetNodeByIdentifier(name) for name in names]
        versions = [node.GetVersion() for node in nodes]
        self.assertEqual(versions, [
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(1),
            Ndr.Version(2, 0),
            Ndr.Version(2, 1),
            Ndr.Version()
        ])

        # Check default versions.
        names = sorted([
            name for name in registry.GetNodeIdentifiers(
                filter=Ndr.VersionFilterDefaultOnly) if name.startswith('pxr_')
        ])
        self.assertEqual(names, [
            'pxr_nd_float', 'pxr_nd_integer', 'pxr_nd_string',
            'pxr_nd_vector_2', 'pxr_nd_vector_noversion'
        ])
        nodes = [registry.GetNodeByIdentifier(name) for name in names]
        versions = [node.GetVersion() for node in nodes]
        self.assertEqual(versions, [
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(2, 0),
            Ndr.Version()
        ])
Beispiel #15
0
    def test_NodeDiscovery(self):
        """
        Test MaterialX node discovery.
        """
        registry = Sdr.Registry()

        # Check node identifiers.
        names = sorted(
            registry.GetNodeIdentifiers('UsdMtlxTestNode',
                                        Ndr.VersionFilterAllVersions))
        self.assertEqual(names, [
            'pxr_nd_boolean', 'pxr_nd_float', 'pxr_nd_integer',
            'pxr_nd_string', 'pxr_nd_vector', 'pxr_nd_vector_2',
            'pxr_nd_vector_2_1', 'pxr_nd_vector_noversion'
        ])

        # Check node names.
        names = sorted(registry.GetNodeNames('UsdMtlxTestNode'))
        self.assertEqual(names, [
            'pxr_nd_boolean', 'pxr_nd_float', 'pxr_nd_integer',
            'pxr_nd_string', 'pxr_nd_vector'
        ])

        # Get by family.  Non-default versions should be dropped.
        #
        # Because pxr_nd_vector_noversion has no version at all the
        # discovery assumes it's the default version despite appearances
        # to the human eye.
        nodes = registry.GetNodesByFamily('UsdMtlxTestNode')
        names = sorted([node.GetIdentifier() for node in nodes])
        self.assertEqual(names, [
            'pxr_nd_boolean', 'pxr_nd_float', 'pxr_nd_integer',
            'pxr_nd_string', 'pxr_nd_vector_2', 'pxr_nd_vector_noversion'
        ])

        # Check all versions.
        # Note that this sorting depends on how unique identifiers are
        # constructed so the order of items on the right hand side of
        # the assertion must stay in sync with that.
        names = sorted([
            name for name in registry.GetNodeIdentifiers(
                filter=Ndr.VersionFilterAllVersions) if name.startswith('pxr_')
        ])
        nodes = [registry.GetNodeByIdentifier(name) for name in names]
        versions = [node.GetVersion() for node in nodes]
        self.assertEqual(versions, [
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(1),
            Ndr.Version(2, 0),
            Ndr.Version(2, 1),
            Ndr.Version()
        ])

        # Check default versions.
        names = sorted([
            name for name in registry.GetNodeIdentifiers(
                filter=Ndr.VersionFilterDefaultOnly) if name.startswith('pxr_')
        ])
        self.assertEqual(names, [
            'pxr_nd_boolean', 'pxr_nd_booleanDefaults', 'pxr_nd_float',
            'pxr_nd_integer', 'pxr_nd_string', 'pxr_nd_vector_2',
            'pxr_nd_vector_noversion'
        ])
        nodes = [registry.GetNodeByIdentifier(name) for name in names]
        versions = [node.GetVersion() for node in nodes]
        self.assertEqual(versions, [
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(),
            Ndr.Version(2, 0),
            Ndr.Version()
        ])

        # Check default values of boolean inputs:
        node = registry.GetNodeByIdentifier("pxr_nd_booleanDefaults")
        self.assertTrue(node)
        trueInput = node.GetInput("inTrue")
        self.assertTrue(trueInput.GetDefaultValue())
        self.assertTrue(trueInput.GetDefaultValueAsSdfType())
        falseInput = node.GetInput("inFalse")
        self.assertFalse(falseInput.GetDefaultValue())
        self.assertFalse(falseInput.GetDefaultValueAsSdfType())
Beispiel #16
0
    def test_SdrShaderNodesForLights(self):
        """
        Test the automatic registration of SdrShaderNodes for all the UsdLux
        light types.
        """

        # The expected shader node inputs that should be found for all of our
        # UsdLux light types.
        expectedLightInputNames = [
            # LightAPI
            'color', 
            'colorTemperature', 
            'diffuse', 
            'enableColorTemperature', 
            'exposure', 
            'intensity', 
            'normalize', 
            'specular',

            # ShadowAPI
            'shadow:color',
            'shadow:distance',
            'shadow:enable',
            'shadow:falloff',
            'shadow:falloffGamma',

            # ShapingAPI
            'shaping:cone:angle',
            'shaping:cone:softness',
            'shaping:focus',
            'shaping:focusTint',
            'shaping:ies:angleScale',
            'shaping:ies:file',
            'shaping:ies:normalize'
            ]

        # Map of the names of the expected light nodes to the additional inputs
        # we expect for those types.
        expectedLightNodes = {
            'CylinderLight' : ['length', 'radius'],
            'DiskLight' : ['radius'],
            'DistantLight' : ['angle'],
            'DomeLight' : ['texture:file', 'texture:format'],
            'GeometryLight' : [],
            'PortalLight' : [],
            'RectLight' : ['width', 'height', 'texture:file'],
            'SphereLight' : ['radius'],
            'MeshLight' : [],
            'VolumeLight' : []
            }

        # Get all the derived types of UsdLuxBoundableLightBase and 
        # UsdLuxNonboundableLightBase that are defined in UsdLux
        lightTypes = list(filter(
            Plug.Registry().GetPluginWithName("usdLux").DeclaresType,
            Tf.Type(UsdLux.BoundableLightBase).GetAllDerivedTypes() +
            Tf.Type(UsdLux.NonboundableLightBase).GetAllDerivedTypes()))
        self.assertTrue(lightTypes)

        # Augment lightTypes to include MeshLightAPI and VolumeLightAPI
        lightTypes.append(
            Tf.Type.FindByName('UsdLuxMeshLightAPI'))
        lightTypes.append(
            Tf.Type.FindByName('UsdLuxVolumeLightAPI'))

        # Verify that at least one known light type is in our list to guard
        # against this giving false positives if no light types are available.
        self.assertIn(UsdLux.RectLight, lightTypes)
        self.assertEqual(len(lightTypes), len(expectedLightNodes))

        stage = Usd.Stage.CreateInMemory()
        prim = stage.DefinePrim("/Prim")

        usdSchemaReg = Usd.SchemaRegistry()
        for lightType in lightTypes:

            print("Test SdrNode for schema type " + str(lightType))
            
            if usdSchemaReg.IsAppliedAPISchema(lightType):
                prim.ApplyAPI(lightType)
            else:
                typeName = usdSchemaReg.GetConcreteSchemaTypeName(lightType)
                if not typeName:
                    continue
                prim.SetTypeName(typeName)
            light = UsdLux.LightAPI(prim)
            self.assertTrue(light)
            sdrIdentifier = light.GetShaderId([])
            self.assertTrue(sdrIdentifier)
            prim.ApplyAPI(UsdLux.ShadowAPI)
            prim.ApplyAPI(UsdLux.ShapingAPI)

            # Every concrete light type and some API schemas (with appropriate
            # shaderId as sdr Identifier) in usdLux domain will have an 
            # SdrShaderNode with source type 'USD' registered for it under its 
            # USD schema type name. 
            node = Sdr.Registry().GetNodeByIdentifier(sdrIdentifier, ['USD'])
            self.assertTrue(node is not None)
            self.assertIn(sdrIdentifier, expectedLightNodes)

            # Names, identifier, and role for the node all match the USD schema
            # type name
            self.assertEqual(node.GetIdentifier(), sdrIdentifier)
            self.assertEqual(node.GetName(), sdrIdentifier)
            self.assertEqual(node.GetImplementationName(), sdrIdentifier)
            self.assertEqual(node.GetRole(), sdrIdentifier)
            self.assertTrue(node.GetInfoString().startswith(sdrIdentifier))

            # The context is always 'light' for lights. 
            # Source type is 'USD'
            self.assertEqual(node.GetContext(), 'light')
            self.assertEqual(node.GetSourceType(), 'USD')

            # Help string is generated and encoded in the node's metadata (no
            # need to verify the specific wording).
            self.assertTrue(set(node.GetMetadata().keys()), {'primvars', 'help'})
            self.assertEqual(node.GetMetadata()["help"], node.GetHelp())

            # Source code and URIs are all empty.
            self.assertFalse(node.GetSourceCode())
            self.assertFalse(node.GetResolvedDefinitionURI())
            self.assertFalse(node.GetResolvedImplementationURI())

            # Other classifications are left empty.
            self.assertFalse(node.GetCategory())
            self.assertFalse(node.GetDepartments())
            self.assertFalse(node.GetFamily())
            self.assertFalse(node.GetLabel())
            self.assertFalse(node.GetVersion())
            self.assertFalse(node.GetAllVstructNames())
            self.assertEqual(node.GetPages(), [''])

            # The node will be valid for our light types.
            self.assertTrue(node.IsValid())

            # Helper for comparing an SdrShaderProperty from node to the 
            # corresponding UsdShadeInput/UsdShadeOutput from a UsdLux light
            def _CompareLightPropToNodeProp(nodeInput, primInput):
                # Input names and default values match.
                primDefaultValue = primInput.GetAttr().Get()
                self.assertEqual(nodeInput.GetName(), primInput.GetBaseName())
                self.assertEqual(nodeInput.GetDefaultValue(), primDefaultValue)

                # Some USD property types don't match exactly one to one and are
                # converted to different types. In particular relevance to 
                # lights and Token becomes String.
                expectedTypeName = primInput.GetTypeName()
                # Array valued attributes have their array size determined from
                # the default value and will be converted to scalar in the 
                # SdrProperty if the array size is zero.
                if expectedTypeName.isArray:
                    if not primDefaultValue or len(primDefaultValue) == 0:
                        expectedTypeName = expectedTypeName.scalarType
                elif expectedTypeName == Sdf.ValueTypeNames.Token:
                    expectedTypeName = Sdf.ValueTypeNames.String 
                # Bool SdfTypes should Have Int SdrTypes, but still return as
                # Bool when queried for GetTypeAsSdfType
                if expectedTypeName == Sdf.ValueTypeNames.Bool:
                    self.assertEqual(nodeInput.GetType(),
                            Sdf.ValueTypeNames.Int)
                # Verify the node's input type maps back to USD property's type
                # (with the noted above exceptions).
                self.assertEqual(
                    nodeInput.GetTypeAsSdfType()[0], expectedTypeName,
                    msg="{}.{} Type {} != {}".format(
                        str(node.GetName()),
                        str(nodeInput.GetName()),
                        str(nodeInput.GetTypeAsSdfType()[0]),
                        str(expectedTypeName)))
                # If the USD property type is an Asset, it will be listed in 
                # the node's asset identifier inputs.
                if expectedTypeName == Sdf.ValueTypeNames.Asset:
                    self.assertIn(nodeInput.GetName(), 
                                  node.GetAssetIdentifierInputNames())

            # There will be a one to one correspondence between node inputs
            # and prim inputs. Note that the prim may have additional inputs
            # because of auto applied API schemas, but we only need to verify
            # that the node has ONLY the expected inputs and the prim at least
            # has those input proerties.
            expectedInputNames = \
                expectedLightInputNames + expectedLightNodes[sdrIdentifier]
            # Verify node has exactly the expected inputs.
            self.assertEqual(sorted(expectedInputNames),
                             sorted(node.GetInputNames()))
            # Verify each node input matches a prim input.
            for inputName in expectedInputNames:
                nodeInput = node.GetInput(inputName)
                primInput = light.GetInput(inputName)
                self.assertFalse(nodeInput.IsOutput())
                _CompareLightPropToNodeProp(nodeInput, primInput)

            # None of the UsdLux base lights have outputs
            self.assertEqual(node.GetOutputNames(), [])
            self.assertEqual(light.GetOutputs(onlyAuthored=False), [])

            # The reverse is tested just above, but for all asset identifier
            # inputs listed for the node there is a corresponding asset value
            # input property on the prim.
            for inputName in node.GetAssetIdentifierInputNames():
                self.assertEqual(light.GetInput(inputName).GetTypeName(),
                                 Sdf.ValueTypeNames.Asset)

            # These primvars come from sdrMetadata on the prim itself which
            # isn't supported for light schemas so it will always be empty.
            self.assertFalse(node.GetPrimvars())
            # sdrMetadata on input properties is supported so additional 
            # primvar properties will correspond to prim inputs with that 
            # metadata set.
            for propName in node.GetAdditionalPrimvarProperties():
                self.assertTrue(light.GetInput(propName).GetSdrMetadataByKey(
                    'primvarProperty'))

            # Default input can also be specified in the property's sdrMetadata.
            if node.GetDefaultInput():
                defaultInput = light.GetInput(
                    node.GetDefaultInput().GetName())
                self.assertTrue(defaultInput.GetSdrMetadataByKey('defaultInput'))
Beispiel #17
0
def UpdateSchemaWithSdrNode(schemaLayer,
                            sdrNode,
                            renderContext="",
                            overrideIdentifier=""):
    """
    Updates the given schemaLayer with primSpec and propertySpecs from sdrNode
    metadata. 

    A renderContext can be provided which is used in determining the
    shaderId namespace, which follows the pattern: 
    "<renderContext>:<SdrShaderNodeContext>:shaderId". Note that we are using a
    node's context (SDR_NODE_CONTEXT_TOKENS) here to construct the shaderId
    namespace, so shader parsers should make sure to use appropriate
    SDR_NODE_CONTEXT_TOKENS in the node definitions.

    overrideIdentifier parameter is the identifier which should be used when 
    the identifier of the node being processed differs from the one Sdr will 
    discover at runtime, such as when this function is def a node constructed 
    from an explicit asset path. This should only be used when clients know the 
    identifier being passed is the true identifier which sdr Runtime will 
    provide when querying using GetShaderNodeByNameAndType, etc.

    It consumes the following attributes (that manifest as Sdr 
    metadata) in addition to many of the standard Sdr metadata
    specified and parsed (via its parser plugin).

    Node Level Metadata:
        - "schemaName": Name of the new schema populated from the given sdrNode
          (Required)
        - "schemaKind": Specifies the UsdSchemaKind for the schema being
          populated from the sdrNode. (Note that this does not support
          multiple apply schema kinds).
        - "schemaBase": Base schema from which the new schema should inherit
          from. Note this defaults to "APISchemaBase" for an API schema or 
          "Typed" for a concrete scheme.
        - "usdSchemaClass": Specifies the equivalent schema directly generated
          by USD (sourceType: USD). This is used to make sure duplicate
          properties already specified in the USD schema are not populated in
          the new API schema. Note this is only used when we are dealing with an
          API schema.
        - "apiSchemaAutoApplyTo": The schemas to which the sdrNode populated 
          API schema will autoApply to.
        - "apiSchemaCanOnlyApplyTo": If specified, the API schema generated 
          from the sdrNode can only be validly applied to this set of schemas.
        - "providesUsdShadeConnectableAPIBehavior": Used to enable a 
          connectability behavior for an API schema.
        - "isUsdShadeContainer": Only used when
          providesUsdShadeConnectableAPIBehavior is set to true. Marks the
          connectable prim as a UsdShade container type.
        - "requiresUsdShadeEncapsulation": Only used when
          providesUsdShadeConnectableAPIBehavior is set to true. Configures the
          UsdShade encapsulation rules governing its connectableBehavior.
        - "tfTypeNameSuffix": Class name which will get registered with TfType 
          system. This gets appended to the domain name to register with TfType.

    Property Level Metadata:
        - USD_VARIABILITY: Property level metadata which specifies a specific 
          sdrNodeProperty should have its USD variability set to Uniform or 
          Varying
        - USD_SUPPRESS_PROPERTY: A property level metadata which determines if 
          the property should be suppressed from translation from args to 
          property spec.

    Sdr Property Metadata to SdfPropertySpec Translations
        - A "null" value for Widget sdrProperty metadata translates to 
          SdfPropertySpec Hidden metadata.
        - SdrProperty's Help metadata (Label metadata if Help metadata not 
          provided) translates to SdfPropertySpec's Documentation string 
          metadata.
        - SdrProperty's Page metadata translates to SdfPropertySpec's
          DisplayGroup metadata.
        - SdrProperty's Label metadata translates to SdfPropertySpec's
          DisplayName metadata.
        - SdrProperty's Options translates to SdfPropertySpec's AllowedTokens.
        - SdrProperty's Default value translates to SdfPropertySpec's Default
          value.
        - Connectable input properties translates to InterfaceOnly
          SdfPropertySpec's CONNECTABILITY.
    """

    import distutils.util
    import os

    # Early exit on invalid parameters
    if not schemaLayer:
        Tf.Warn("No Schema Layer provided")
        return
    if not sdrNode:
        Tf.Warn("No valid sdrNode provided")
        return

    sdrNodeMetadata = sdrNode.GetMetadata()

    if SchemaDefiningKeys.SCHEMA_NAME not in sdrNodeMetadata:
        Tf.Warn("Sdr Node (%s) does not define a schema name metadata." \
                %(sdrNode.GetName()))
        return
    schemaName = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_NAME]
    if not Tf.IsValidIdentifier(schemaName):
        Tf.RaiseRuntimeError(
            "schemaName (%s) is an invalid identifier; "
            "Provide a valid USD identifer for schemaName, example (%s) " %
            (schemaName, Tf.MakeValidIdentifier(schemaName)))

    tfTypeNameSuffix = None
    if SchemaDefiningKeys.TF_TYPENAME_SUFFIX in sdrNodeMetadata:
        tfTypeNameSuffix = sdrNodeMetadata[
            SchemaDefiningKeys.TF_TYPENAME_SUFFIX]
        if not Tf.IsValidIdentifier(tfTypeNameSuffix):
            Tf.RaiseRuntimeError("tfTypeNameSuffix (%s) is an invalid " \
                    "identifier" %(tfTypeNameSuffix))

    if SchemaDefiningKeys.SCHEMA_KIND not in sdrNodeMetadata:
        schemaKind = SchemaDefiningMiscConstants.TYPED_SCHEMA
    else:
        schemaKind = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_KIND]

    # Note: We are not working on dynamic multiple apply schemas right now.
    isAPI = schemaKind == SchemaDefiningMiscConstants.SINGLE_APPLY_SCHEMA
    # Fix schemaName and warn if needed
    if isAPI and \
        not schemaName.endswith(SchemaDefiningMiscConstants.API_STRING):
        Tf.Warn("node metadata implies the generated schema being created is "
                "an API schema, fixing schemaName to reflect that")
        schemaName = schemaName + SchemaDefiningMiscConstants.API_STRING

    if isAPI and tfTypeNameSuffix and \
        not tfTypeNameSuffix.endswith(SchemaDefiningMiscConstants.API_STRING):
        Tf.Warn("node metadata implies the generated schema being created "
                "is an API schema, fixing tfTypeNameSuffix to reflect that")
        tfTypeNameSuffix = tfTypeNameSuffix + \
                SchemaDefiningMiscConstants.API_STRING

    if SchemaDefiningKeys.SCHEMA_BASE not in sdrNodeMetadata:
        Tf.Warn("No schemaBase specified in node metadata, defaulting to "
                "APISchemaBase for API schemas else Typed")
        schemaBase = SchemaDefiningMiscConstants.API_SCHEMA_BASE if isAPI \
                else SchemaDefiningMiscConstants.TYPED_SCHEMA
    else:
        schemaBase = sdrNodeMetadata[SchemaDefiningKeys.SCHEMA_BASE]

    apiSchemaAutoApplyTo = None
    if SchemaDefiningKeys.API_SCHEMA_AUTO_APPLY_TO in sdrNodeMetadata:
        apiSchemaAutoApplyTo = \
            sdrNodeMetadata[SchemaDefiningKeys.API_SCHEMA_AUTO_APPLY_TO] \
                .split('|')

    apiSchemaCanOnlyApplyTo = None
    if SchemaDefiningKeys.API_SCHEMA_CAN_ONLY_APPLY_TO in sdrNodeMetadata:
        apiSchemaCanOnlyApplyTo = \
            sdrNodeMetadata[SchemaDefiningKeys.API_SCHEMA_CAN_ONLY_APPLY_TO] \
                .split('|')

    providesUsdShadeConnectableAPIBehavior = False
    if SchemaDefiningKeys.PROVIDES_USD_SHADE_CONNECTABLE_API_BEHAVIOR in \
            sdrNodeMetadata:
        providesUsdShadeConnectableAPIBehavior = \
            distutils.util.strtobool(sdrNodeMetadata[SchemaDefiningKeys. \
                PROVIDES_USD_SHADE_CONNECTABLE_API_BEHAVIOR])

    usdSchemaClass = None
    if isAPI and SchemaDefiningKeys.USD_SCHEMA_CLASS in sdrNodeMetadata:
        usdSchemaClass = \
            sdrNodeMetadata[SchemaDefiningKeys.USD_SCHEMA_CLASS]

    primSpec = schemaLayer.GetPrimAtPath(schemaName)

    if (primSpec):
        # if primSpec already exist, remove entirely and recreate using the
        # parsed sdr node
        if primSpec.nameParent:
            del primSpec.nameParent.nameChildren[primSpec.name]
        else:
            del primSpec.nameRoot.nameChildren[primSpec.name]

    primSpec = Sdf.PrimSpec(schemaLayer, schemaName, Sdf.SpecifierClass,
                            "" if isAPI else schemaName)

    primSpec.inheritPathList.explicitItems = ["/" + schemaBase]

    primSpecCustomData = {}
    if isAPI:
        primSpecCustomData["apiSchemaType"] = schemaKind
    if tfTypeNameSuffix:
        # Defines this classname for TfType system
        # can help avoid duplicate prefix with domain and className
        # Tf type system will automatically pick schemaName as tfTypeName if
        # this is not set!
        primSpecCustomData["className"] = tfTypeNameSuffix

    if apiSchemaAutoApplyTo:
        primSpecCustomData['apiSchemaAutoApplyTo'] = \
            Vt.TokenArray(apiSchemaAutoApplyTo)
    if apiSchemaCanOnlyApplyTo:
        primSpecCustomData['apiSchemaCanOnlyApplyTo'] = \
            Vt.TokenArray(apiSchemaCanOnlyApplyTo)

    if providesUsdShadeConnectableAPIBehavior:
        extraPlugInfo = {
            SchemaDefiningKeys.PROVIDES_USD_SHADE_CONNECTABLE_API_BEHAVIOR \
                    : True
        }
        for propKey in [SchemaDefiningKeys.IS_USD_SHADE_CONTAINER, \
                SchemaDefiningKeys.REQUIRES_USD_SHADE_ENCAPSULATION]:
            if propKey in sdrNodeMetadata:
                # Since we want to assign the types for these to bool and
                # because in python boolean type is a subset of int, we need to
                # do following instead of assign the propValue directly.
                propValue = distutils.util.strtobool(sdrNodeMetadata[propKey])
                extraPlugInfo[propKey] = bool(propValue)

        primSpecCustomData['extraPlugInfo'] = extraPlugInfo

    primSpec.customData = primSpecCustomData

    doc = sdrNode.GetHelp()
    if doc != "":
        primSpec.documentation = doc

    # gather properties from node directly generated from USD (sourceType: USD)
    # Use the usdSchemaClass tag when the generated schema being defined is an
    # API schema
    usdSchemaNode = None
    if usdSchemaClass:
        reg = Sdr.Registry()
        if usdSchemaClass.endswith(SchemaDefiningMiscConstants.API_STRING):
            # This usd schema is an API schema, we need to extract the shader
            # identifier from its primDef's shaderId field.
            primDef = Usd.SchemaRegistry().FindAppliedAPIPrimDefinition(
                usdSchemaClass)
            if primDef:
                # We are dealing with USD source type here, hence no render
                # context is required but we can still borrow node context
                # information from the sdrNode in question, since the usd source
                # type node should also belong to the same context.
                shaderIdAttrName = Sdf.Path.JoinIdentifier( \
                        sdrNode.GetContext(), PropertyDefiningKeys.SHADER_ID)
                sdrIdentifier = primDef.GetAttributeFallbackValue(
                    shaderIdAttrName)
                if sdrIdentifier != "":
                    usdSchemaNode = reg.GetNodeByIdentifierAndType(
                        sdrIdentifier,
                        SchemaDefiningMiscConstants.USD_SOURCE_TYPE)
                else:
                    Tf.Warn("No sourceId authored for '%s'." %
                            (usdSchemaClass))
            else:
                Tf.Warn("Illegal API schema provided for the usdSchemaClass "
                        "metadata. No prim definition registered for '%s'" %
                        (usdSchemaClass))

        else:
            usdSchemaNode = reg.GetNodeByIdentifierAndType(
                usdSchemaClass, SchemaDefiningMiscConstants.USD_SOURCE_TYPE)

    # Create attrSpecs from input parameters
    for propName in sdrNode.GetInputNames():
        _CreateAttrSpecFromNodeAttribute(primSpec, sdrNode.GetInput(propName),
                                         usdSchemaNode)

    # Create attrSpecs from output parameters
    for propName in sdrNode.GetOutputNames():
        _CreateAttrSpecFromNodeAttribute(primSpec, sdrNode.GetOutput(propName),
                                         usdSchemaNode, False)

    # Create token shaderId attrSpec
    shaderIdAttrName = Sdf.Path.JoinIdentifier( \
            [renderContext, sdrNode.GetContext(), PropertyDefiningKeys.SHADER_ID])
    shaderIdAttrSpec = Sdf.AttributeSpec(primSpec, shaderIdAttrName,
                                         Sdf.ValueTypeNames.Token,
                                         Sdf.VariabilityUniform)

    # Since users shouldn't need to be aware of shaderId attribute, we put this
    # in "Internal" displayGroup.
    shaderIdAttrSpec.displayGroup = PropertyDefiningKeys.INTERNAL_DISPLAY_GROUP

    # Use the identifier if explicitly provided, (it could be a shader node
    # queried using an explicit path), else use sdrNode's registered identifier.
    nodeIdentifier = overrideIdentifier if overrideIdentifier else \
            sdrNode.GetIdentifier()
    shaderIdAttrSpec.default = nodeIdentifier

    # Extra attrSpec
    schemaBasePrimDefinition = \
        Usd.SchemaRegistry().FindConcretePrimDefinition(schemaBase)
    if schemaBasePrimDefinition and \
        SchemaDefiningMiscConstants.NodeDefAPI in \
        schemaBasePrimDefinition.GetAppliedAPISchemas():
        infoIdAttrSpec = Sdf.AttributeSpec(primSpec, \
                UsdShade.Tokens.infoId, Sdf.ValueTypeNames.Token, \
                Sdf.VariabilityUniform)
        infoIdAttrSpec.default = nodeIdentifier

    schemaLayer.Save()
Beispiel #18
0
    def test_SdrShaderNodesForLights(self):
        """
        Test the automatic registration of SdrShaderNodes for all the UsdLux
        light types.
        """
        # Get all the derived types of UsdLuxLight
        lightTypes = Tf.Type(UsdLux.Light).GetAllDerivedTypes()
        self.assertTrue(lightTypes)
        # Verify that at least one known light type is in our list to guard
        # against this giving false positives if no light types are available.
        self.assertIn(UsdLux.RectLight, lightTypes)

        stage = Usd.Stage.CreateInMemory()
        prim = stage.DefinePrim("/Prim")

        for lightType in lightTypes:
            # Every concrete light type will have an SdrShaderNode with source
            # type 'USD' registered for it under its USD schema type name.
            typeName = Usd.SchemaRegistry.GetConcreteSchemaTypeName(lightType)
            node = Sdr.Registry().GetNodeByName(typeName, ['USD'])
            self.assertTrue(node.IsValid())

            # Set the prim to the light type so we can cross check node inputs
            # with the light prim built-in properties.
            prim.SetTypeName(typeName)
            light = UsdLux.Light(prim)
            self.assertTrue(light)

            # Names, identifier, and role for the node all match the USD schema
            # type name
            self.assertEqual(node.GetIdentifier(), typeName)
            self.assertEqual(node.GetName(), typeName)
            self.assertEqual(node.GetImplementationName(), typeName)
            self.assertEqual(node.GetRole(), typeName)
            self.assertTrue(node.GetInfoString().startswith(typeName))

            # The context is always 'light'. Source type is 'USD'
            self.assertEqual(node.GetContext(), 'light')
            self.assertEqual(node.GetSourceType(), 'USD')

            # Help string is generated and encoded in the node's metadata (no
            # need to verify the specific wording).
            self.assertTrue(set(node.GetMetadata().keys()), {'primvars', 'help'})
            self.assertEqual(node.GetMetadata()["help"], node.GetHelp())

            # Source code and URIs are all empty.
            self.assertFalse(node.GetSourceCode())
            self.assertFalse(node.GetResolvedDefinitionURI())
            self.assertFalse(node.GetResolvedImplementationURI())

            # Other classifications are left empty.
            self.assertFalse(node.GetCategory())
            self.assertFalse(node.GetDepartments())
            self.assertFalse(node.GetFamily())
            self.assertFalse(node.GetLabel())
            self.assertFalse(node.GetVersion())
            self.assertFalse(node.GetAllVstructNames())
            self.assertEqual(node.GetPages(), [''])

            # Helper for comparing an SdrShaderProperty from node to the 
            # corresponding UsdShadeInput/UsdShadeOutput from a UsdLuxLight
            def _CompareLightPropToNodeProp(nodeInput, lightInput):
                # Input names and default values match.
                self.assertEqual(nodeInput.GetName(), lightInput.GetBaseName())
                self.assertEqual(nodeInput.GetDefaultValue(),
                                 lightInput.GetAttr().Get())

                # Some USD property types don't match exactly one to one and are
                # converted to different types. In particular relevance to 
                # lights, Bool becomes Int and Token becomes String.
                expectedTypeName = lightInput.GetTypeName()
                if expectedTypeName == Sdf.ValueTypeNames.Bool:
                    expectedTypeName = Sdf.ValueTypeNames.Int 
                elif expectedTypeName == Sdf.ValueTypeNames.Token:
                    expectedTypeName = Sdf.ValueTypeNames.String 
                # Verify the node's input type maps back to USD property's type
                # (with the noted above exceptions).
                self.assertEqual(
                    nodeInput.GetTypeAsSdfType()[0], expectedTypeName,
                    msg="Type {} != {}".format(
                        str(nodeInput.GetTypeAsSdfType()[0]),
                        str(expectedTypeName)))
                # If the USD property type is an Asset, it will be listed in 
                # the node's asset indentifier inputs.
                if expectedTypeName == Sdf.ValueTypeNames.Asset:
                    self.assertIn(nodeInput.GetName(), 
                                  node.GetAssetIdentifierInputNames())

            # There will be a one to one correspondence between node inputs
            # and light prim inputs.
            nodeInputs = [node.GetInput(i) for i in node.GetInputNames()]
            lightInputs = light.GetInputs()
            for nodeInput, lightInput in zip(nodeInputs, lightInputs):
                self.assertFalse(nodeInput.IsOutput())
                _CompareLightPropToNodeProp(nodeInput, lightInput)

            # There will also be a one to one correspondence between node 
            # outputs and light prim outputs.
            nodeOutputs = [node.GetOutput(i) for i in node.GetOutputNames()]
            lightOutputs = light.GetOutputs()
            for nodeOutput, lightOutput in zip(nodeOutputs, lightOutputs):
                self.assertTrue(nodeOutput.IsOutput())
                _CompareLightPropToNodeProp(nodeOutput, lightOutput)

            # The reverse is tested just above, but for all asset identifier
            # inputs listed for the node there is a corresponding asset value
            # input property on the light prim.
            for inputName in node.GetAssetIdentifierInputNames():
                self.assertEqual(light.GetInput(inputName).GetTypeName(),
                                 Sdf.ValueTypeNames.Asset)

            # These primvars come from sdrMetadata on the prim itself which
            # isn't supported for light schemas so it will alwasy be empty.
            self.assertFalse(node.GetPrimvars())
            # sdrMetadata on input properties is supported so additional 
            # primvar properties will correspond to light inputs with that 
            # metadata set.
            for propName in node.GetAdditionalPrimvarProperties():
                self.assertTrue(light.GetInput(propName).GetSdrMetadataByKey(
                    'primvarProperty'))

            # Default input can also be specified in the property's sdrMetadata.
            if node.GetDefaultInput():
                defaultLightInput = light.GetInput(
                    node.GetDefaultInput().GetName())
                self.assertTrue(lightInput.GetSdrMetadataByKey('defaultInput'))