示例#1
0
    def test_AppliedSchemaWithDefaultBehavior(self):
        stage = Usd.Stage.CreateInMemory()

        # imparts connectability traits to UsdShadeTestTyped prim while still
        # having no connectability trails on the type itself.
        self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI(
            _SchemaTypeFindByName('UsdShadeTestTyped')))
        usdShadeTestTyped = stage.DefinePrim("/UsdShadeTestTyped",
            "UsdShadeTestTyped")
        usdShadeTestTypedConn = UsdShade.ConnectableAPI(usdShadeTestTyped)
        self.assertFalse(usdShadeTestTypedConn)
        self.assertFalse(usdShadeTestTypedConn.RequiresEncapsulation())

        usdShadeTestTyped.AddAppliedSchema("DefaultConnectableBehaviorAPI")
        self.assertTrue(usdShadeTestTypedConn)
        self.assertTrue(usdShadeTestTypedConn.RequiresEncapsulation())
        self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI(
            _SchemaTypeFindByName('UsdShadeTestTyped')))

        # modify/override connectability behavior for an already connectable
        # type
        material = UsdShade.Material.Define(stage, '/Mat')
        materialPrim = material.GetPrim()
        materialPrimConn = UsdShade.ConnectableAPI(materialPrim)
        self.assertTrue(materialPrimConn)
        self.assertTrue(materialPrimConn.IsContainer())
        # Apply overriding connectablility behavior (default has Container as
        # false)
        materialPrim.AddAppliedSchema("DefaultConnectableBehaviorAPI")
        # Following should also call GetBehavior and updating the registered
        # behavior for this material Prim
        self.assertTrue(materialPrimConn)
        self.assertFalse(materialPrimConn.IsContainer())
    def test_InvalidAppliedSchemaWithDefaultBehavior(self):
        stage = Usd.Stage.CreateInMemory()

        # create a typeless prim, add a multi-apply schema
        multiAPIPrim = stage.DefinePrim("/PrimA")
        self.assertEqual(multiAPIPrim.GetTypeName(), "")
        Usd.CollectionAPI.Apply(multiAPIPrim, "fanciness")
        connectableMultiAPIPrim = UsdShade.ConnectableAPI(multiAPIPrim)
        self.assertFalse(connectableMultiAPIPrim)
        self.assertFalse(connectableMultiAPIPrim.IsContainer())

        # create a typeless prim, add a non-existent API Schema
        invalidAPIPrim = stage.DefinePrim("/PrimB")
        self.assertEqual(invalidAPIPrim.GetTypeName(), "")
        invalidAPIPrim.AddAppliedSchema("NoSuchLuckInvalidAPISchemaAPI")
        connectableInvalidAPIPrim = UsdShade.ConnectableAPI(invalidAPIPrim)
        self.assertFalse(connectableInvalidAPIPrim)
        self.assertFalse(connectableInvalidAPIPrim.IsContainer())

        # create a typeless prim, add a typed schema as an API Schema!
        typedAPIPrim = stage.DefinePrim("/PrimC")
        self.assertEqual(typedAPIPrim.GetTypeName(), "")
        typedAPIPrim.AddAppliedSchema("Material")
        connectableTypedAPIPrim = UsdShade.ConnectableAPI(typedAPIPrim)
        self.assertFalse(connectableTypedAPIPrim)
        self.assertFalse(connectableTypedAPIPrim.IsContainer())
    def test_AncestorAndPlugConfiguredTypedSchema(self):
        stage = Usd.Stage.CreateInMemory()

        # Test a type which imparts connectableAPIBehavior through its plug
        # metadata and not having an explicit behavior registered.
        self.assertTrue(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                _SchemaTypeFindByName("UsdShadeTestPlugConfiguredType")))
        usdShadeTestPlugConfiguredType = \
            stage.DefinePrim("/UsdShadeTestPlugConfiguredType",
                    "UsdShadeTestPlugConfiguredType")
        connectable = UsdShade.ConnectableAPI(usdShadeTestPlugConfiguredType)
        self.assertTrue(connectable)
        self.assertFalse(connectable.IsContainer())
        self.assertFalse(connectable.RequiresEncapsulation())

        # Test a type which imparts connectableAPIBehavior through its ancestor
        self.assertTrue(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                _SchemaTypeFindByName("UsdShadeTestAncestorConfiguredType")))
        usdShadeTestAncestorConfiguredType = \
            stage.DefinePrim("/UsdShadeTestAncestorConfiguredType",
                    "UsdShadeTestAncestorConfiguredType")
        connectable2 = UsdShade.ConnectableAPI(
            usdShadeTestAncestorConfiguredType)
        self.assertTrue(connectable2)
        self.assertTrue(connectable2.IsContainer())
        self.assertTrue(connectable2.RequiresEncapsulation())
    def test_AppliedSchemaWithOverridingPlugMetadata(self):
        stage = Usd.Stage.CreateInMemory()

        # imparts connectability traits to UsdShadeTestTyped prim while still
        # having no connectability trails on the type itself.
        self.assertFalse(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                _SchemaTypeFindByName('UsdShadeTestTyped')))
        usdShadeTestTyped = stage.DefinePrim("/UsdShadeTestTyped",
                                             "UsdShadeTestTyped")
        connectable = UsdShade.ConnectableAPI(usdShadeTestTyped)
        self.assertFalse(connectable)
        self.assertFalse(connectable.RequiresEncapsulation())

        # Add ModifiedDefaultConnectableBehaviorAPI apiSchema and see if
        # appropriate connectable behavior gets set for this prim
        usdShadeTestTyped.AddAppliedSchema(
            "ModifiedDefaultConnectableBehaviorAPI")
        self.assertTrue(connectable)
        self.assertTrue(connectable.IsContainer())
        self.assertFalse(connectable.RequiresEncapsulation())
        self.assertFalse(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                _SchemaTypeFindByName('UsdShadeTestTyped')))

        # If multiple applied schemas provide connectableBehavior then the order
        # in which these get applied determines what drives the prim's
        # connectable behavior
        # Also apply the DefaultConnectableBehaviorAPI, connectableBehavior
        # still should remain the same that is the one specified by
        # ModifiedDefaultConnectableBehaviorAPI
        usdShadeTestTyped.AddAppliedSchema("DefaultConnectableBehaviorAPI")
        self.assertTrue(connectable)
        self.assertTrue(connectable.IsContainer())
        self.assertFalse(connectable.RequiresEncapsulation())

        # Does ModifiedDefaultConnectableBehaviorAPI when explicit applied
        # modify the behavior of a UsdShadeMaterial and UsdShadeShader prim
        material = UsdShade.Material.Define(stage, '/Mat')
        materialPrim = material.GetPrim()
        materialPrimConn = UsdShade.ConnectableAPI(materialPrim)
        self.assertTrue(materialPrimConn)
        self.assertTrue(materialPrimConn.IsContainer())
        self.assertTrue(materialPrimConn.RequiresEncapsulation())
        # Apply overriding ModifiedDefaultConnectableBehaviorAPI
        materialPrim.AddAppliedSchema("ModifiedDefaultConnectableBehaviorAPI")
        self.assertTrue(materialPrimConn.IsContainer())
        self.assertFalse(materialPrimConn.RequiresEncapsulation())

        shader = UsdShade.Shader.Define(stage, '/Shader')
        shaderPrim = shader.GetPrim()
        shaderPrimConn = UsdShade.ConnectableAPI(shaderPrim)
        self.assertTrue(shaderPrimConn)
        self.assertFalse(shaderPrimConn.IsContainer())
        self.assertTrue(shaderPrimConn.RequiresEncapsulation())
        # Apply overriding ModifiedDefaultConnectableBehaviorAPI
        shaderPrim.AddAppliedSchema("ModifiedDefaultConnectableBehaviorAPI")
        self.assertTrue(shaderPrimConn.IsContainer())
        self.assertFalse(shaderPrimConn.RequiresEncapsulation())
示例#5
0
    def CheckPrim(self, prim):
        from pxr import UsdGeom, UsdShade

        parent = prim.GetParent()

        # Of course we must allow Boundables under other Boundables, so that
        # schemas like UsdGeom.Pointinstancer can nest their prototypes.  But
        # we disallow a PointInstancer under a Mesh just as we disallow a Mesh
        # under a Mesh, for the same reason: we cannot then independently
        # adjust visibility for the two objects, nor can we reasonably compute
        # the parent Mesh's extent.
        if prim.IsA(UsdGeom.Boundable):
            if parent:
                if self._HasGprimAncestor(parent):
                    self._AddFailedCheck(
                        "Gprim <%s> has an ancestor prim that "
                        "is also a Gprim, which is not allowed." %
                        prim.GetPath())

        connectable = UsdShade.ConnectableAPI(prim)
        # The GetTypeName() check is to work around a bug in
        # ConnectableAPIBehavior registry.
        if prim.GetTypeName() and connectable:
            if parent:
                pConnectable = UsdShade.ConnectableAPI(parent)
                if not parent.GetTypeName():
                    pConnectable = None
                if pConnectable and not pConnectable.IsContainer():
                    # XXX This should be a failure as it is a violation of the
                    # UsdShade OM.  But pragmatically, there are many
                    # authoring tools currently producing this structure, which
                    # does not _currently_ perturb Hydra, so we need to start
                    # with a warning
                    self._AddWarning("Connectable %s <%s> cannot reside "
                                     "under a non-Container Connectable %s" %
                                     (prim.GetTypeName(), prim.GetPath(),
                                      parent.GetTypeName()))
                elif not pConnectable:
                    # it's only OK to have a non-connectable parent if all
                    # the rest of your ancestors are also non-connectable.  The
                    # error message we give is targeted at the most common
                    # infraction, using Scope or other grouping prims inside
                    # a Container like a Material
                    connAnstr = self._FindConnectableAncestor(parent)
                    if connAnstr is not None:
                        self.AddFailedCheck(
                            "Connectable %s <%s> can only have "
                            "Connectable Container ancestors up "
                            "to %s ancestor <%s>, but its parent"
                            "%s is a %s." %
                            (prim.GetTypeName(), prim.GetPath(),
                             connAnstr.GetTypeName(), connAnstr.GetPath(),
                             parent.GetName(), parent.GetTypeName()))
示例#6
0
    def CheckPrim(self, prim):
        # Right now, we find texture referenced by looking at the asset-valued
        # inputs on Connectable prims.
        from pxr import Sdf, Usd, UsdShade

        # Nothing to do if we are allowing all formats, or if
        # we are an untyped prim
        if self._allowedFormats is None or not prim.GetTypeName():
            return

        # Check if the prim is Connectable.
        connectable = UsdShade.ConnectableAPI(prim)
        if not connectable:
            return

        shaderInputs = connectable.GetInputs()
        for ip in shaderInputs:
            attrPath = ip.GetAttr().GetPath()
            if ip.GetTypeName() == Sdf.ValueTypeNames.Asset:
                texFilePath = ip.Get(Usd.TimeCode.EarliestTime())
                # ip may be unauthored and/or connected
                if texFilePath:
                    self._CheckTexture(texFilePath.path, attrPath)
            elif ip.GetTypeName() == Sdf.ValueTypeNames.AssetArray:
                texPathArray = ip.Get(Usd.TimeCode.EarliestTime())
                if texPathArray:
                    for texPath in texPathArray:
                        self._CheckTexture(texPath, attrPath)
    def test_NewPluginRegistrationNotice(self):
        # Add some behavior entries
        self.assertTrue(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                Tf.Type.FindByName('UsdShadeMaterial')))
        self.assertFalse(
            UsdShade.ConnectableAPI.HasConnectableAPI(
                _SchemaTypeFindByName("UsdShadeTestTyped")))

        # check a material's behavior before registering new plugins
        stage = Usd.Stage.CreateInMemory()
        material = UsdShade.Material.Define(stage, "/Mat")
        matConnectable = UsdShade.ConnectableAPI(material)
        self.assertTrue(matConnectable)
        self.assertTrue(matConnectable.IsContainer())

        # register new plugins, to trigger a call to _DidRegisterPlugins, which
        # should prune the behavior cache off any entry which has a null
        # behavior defined
        pr = Plug.Registry()
        testPlugins = pr.RegisterPlugins(os.path.abspath("resources/plugins2"))
        self.assertTrue(len(testPlugins) == 1)

        # check material connectableAPI again if it has the correct behavior
        # still
        self.assertTrue(matConnectable)
        self.assertTrue(matConnectable.IsContainer())
        def SetupShading(stage):
            # First create the shading prims
            UsdGeom.Scope.Define(stage, shadersPath)
            UsdGeom.Scope.Define(stage, materialsPath)
            # .. and as we create each surface, bind the associated material's variant to it
            allMaterials = []
            for material in materialBases:
                materialPrim = UsdShade.Material.Define(
                    stage, MakeMaterialPath(material))
                allMaterials.append(materialPrim.GetPrim())
                for variant in shadeVariations:
                    surface = UsdShade.Shader.Define(
                        stage, MakeSurfacePath(material, variant))
                    colorOut = surface.CreateOutput("out",
                                                    Sdf.ValueTypeNames.Color3f)

                    disp = UsdShade.Shader.Define(
                        stage, MakeDisplacementPath(material, variant))
                    dispOut = disp.CreateOutput('out',
                                                Sdf.ValueTypeNames.Vector3f)

                    pattern = UsdShade.Shader.Define(
                        stage, MakePatternPath(material, variant))
                    patternOut = pattern.CreateOutput(
                        "out", Sdf.ValueTypeNames.FloatArray)

                    with materialPrim.GetEditContextForVariant(variant):
                        surfaceOutput = materialPrim.CreateOutput(
                            "surface", colorOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            surfaceOutput,
                            UsdShade.ConnectableAPI(colorOut.GetPrim()),
                            colorOut.GetBaseName(),
                            UsdShade.AttributeType.Output)

                        displacementOutput = materialPrim.CreateOutput(
                            "displacement", dispOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            displacementOutput, dispOut)

                        patternOutput = materialPrim.CreateOutput(
                            "pattern", patternOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            patternOutput, patternOut)

                        # XXX: If we replace these terminals with UsdShadeOutput's, then
                        ## we can't have these point to prim paths.
                        #surfacePath = MakeSurfacePath(material, variant, 'out')
                        #CreateTerminal(materialPrim, "surface", surfacePath)

                        #dispPath = MakeDisplacementPath(material, variant, 'out')
                        #CreateTerminal(materialPrim, "displacement", dispPath)

                        #CreateTerminal(materialPrim, 'pattern',
                        #MakePatternPath(material, variant, 'out'))

            return allMaterials
    def test_AutoAppliedSchemaWithOverridingPlugMetadata(self):
        stage = Usd.Stage.CreateInMemory()

        autoAppliedPrim = stage.DefinePrim(
            "/Prim", "UsdShadeTestTypedHasAutoApplyContainer")
        connectable = UsdShade.ConnectableAPI(autoAppliedPrim)
        self.assertTrue(connectable)
        self.assertTrue(connectable.RequiresEncapsulation())
        # Note here that by default a UsdShadeConnectableAPIBehavior does not
        # impart a container property to the prim, but plug metadata on the auto
        # applied api schema sets isContainer to true.
        self.assertTrue(connectable.IsContainer())

        shader = UsdShade.Shader.Define(stage, '/Shader')
        shaderPrim = shader.GetPrim()
        shaderPrimConn = UsdShade.ConnectableAPI(shaderPrim)
        self.assertTrue(shaderPrimConn)
        # note that even though autoApplied schema has isContainer set, it does
        # not affect UsdShadeShaders' default behavior, since a type's behavior
        # is stronger than any built-in apiSchemas behavior.
        self.assertFalse(shaderPrimConn.IsContainer())
        self.assertTrue(shaderPrimConn.RequiresEncapsulation())

        autoAppliedPrim2 = stage.DefinePrim(
            "/Prim2", "UsdShadeTestTypedHasAutoApplyRequiresEncapsulation")
        connectable2 = UsdShade.ConnectableAPI(autoAppliedPrim2)
        self.assertTrue(connectable2)
        # Note here that by default a UsdShadeConnectableAPIBehavior has
        # requiresEncapsulation set to True, but plug metadata on the auto
        # applied api schema sets requiresEncapsulation to false.
        self.assertFalse(connectable2.RequiresEncapsulation())
        self.assertFalse(connectable2.IsContainer())

        material = UsdShade.Material.Define(stage, '/Mat')
        materialPrim = material.GetPrim()
        materialPrimConn = UsdShade.ConnectableAPI(materialPrim)
        self.assertTrue(materialPrimConn)
        # note that even though autoApplied schema removed requiresEncapsulation
        # property, it does not affect UsdShadeMaterials' default behavior,
        # since a type's behavior is stronger than any built-in apiSchemas
        # behavior.
        self.assertTrue(materialPrimConn.RequiresEncapsulation())
        self.assertTrue(materialPrimConn.IsContainer())
示例#10
0
 def test_UnconnectableType(self):
     # Test for a bug-fix where unconnectable prim types returned "True"
     # for HasConnectableAPI
     stage = Usd.Stage.CreateInMemory()
     scope = stage.DefinePrim('/Scope', 'Scope')
     self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI(
         Tf.Type.FindByName('UsdGeomScope')))
     unconn = UsdShade.ConnectableAPI(scope)
     self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI(
         Tf.Type.FindByName('UsdGeomScope')))
    def test_AutoAppliedSchemaWithDefaultBehavior(self):
        stage = Usd.Stage.CreateInMemory()

        autoAppliedPrim = stage.DefinePrim(
            "/AutoAppliedPrim", "UsdShadeTestTypedHasAutoApplyDefault")
        autoAppliedPrimConn = UsdShade.ConnectableAPI(autoAppliedPrim)
        # auto applied schema should have provided connectability behavior to
        # this prim type
        # Following should trigger a GetBehavior call also to update the
        # behavior registry
        self.assertTrue(autoAppliedPrimConn)
        self.assertTrue(autoAppliedPrimConn.RequiresEncapsulation())
        self.assertFalse(autoAppliedPrimConn.IsContainer())

        # We also auto apply a DefaultConnectableBehaviorAPI to UsdMaterial, but
        # it should not override its behavior
        material = UsdShade.Material.Define(stage, '/Mat')
        materialPrim = material.GetPrim()
        materialPrimConn = UsdShade.ConnectableAPI(materialPrim)
        self.assertTrue(materialPrimConn)
        self.assertTrue(materialPrimConn.IsContainer())
        self.assertTrue(materialPrimConn.RequiresEncapsulation())
示例#12
0
def _bugStep2(s):
    # create texture coordinate reader 
    stReader = UsdShade.Shader.Define(s, '/Scene/Looks/NewMaterial/STReader')
    stReader.CreateIdAttr('UsdPrimvarReader_float2')
    stReader.CreateInput('varname', Sdf.ValueTypeNames.Token).Set("st")

    # diffuse texture
    diffuseTextureSampler = UsdShade.Shader.Define(s,'/Scene/Looks/NewMaterial/Texture')
    diffuseTextureSampler.CreateIdAttr('UsdUVTexture')
    diffuseTextureSampler.CreateInput('file', Sdf.ValueTypeNames.Asset).Set("test.png")
    diffuseTextureSampler.CreateInput("st", Sdf.ValueTypeNames.Float2).ConnectToSource(stReader, 'result')
    diffuseTextureSampler.CreateOutput('rgb', Sdf.ValueTypeNames.Float3)

    pbrShader = UsdShade.ConnectableAPI(s.GetPrimAtPath('/Scene/Looks/NewMaterial/PbrPreview'))
    pbrShader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).ConnectToSource(diffuseTextureSampler, 'rgb')
 def test_UnconnectableType(self):
     # Test for a fix a bug where unconnectable prim types returned "True"
     # for HasConnectableAPI
     stage = Usd.Stage.CreateInMemory()
     scope = stage.DefinePrim('/Scope', 'Scope')
     self.assertFalse(
         UsdShade.ConnectableAPI.HasConnectableAPI(
             Tf.Type.FindByName('UsdGeomScope')))
     unconn = UsdShade.ConnectableAPI(scope)
     self.assertFalse(
         UsdShade.ConnectableAPI.HasConnectableAPI(
             Tf.Type.FindByName('UsdGeomScope')))
     # Following is called to trigger a GetBehavior call.
     unconn.IsContainer()
     self.assertFalse(
         UsdShade.ConnectableAPI.HasConnectableAPI(
             Tf.Type.FindByName('UsdGeomScope')))
示例#14
0
 def _FindConnectableAncestor(self, prim):
     from pxr import Sdf, UsdShade
     path = prim.GetPath()
     if path in self._connectableAncestorMap:
         return self._connectableAncestorMap[path]
     elif path == Sdf.Path.absoluteRootPath:
         self._connectableAncestorMap[path] = None
         return None
     else:
         val = self._FindConnectableAncestor(prim.GetParent())
         # The GetTypeName() check is to work around a bug in
         # ConnectableAPIBehavior registry.
         if prim.GetTypeName() and not val:
             conn = UsdShade.ConnectableAPI(prim)
             if conn:
                 val = prim
         self._connectableAncestorMap[path] = val
         return val
示例#15
0
        def SetupShading(stage):
            # First create the shading prims
            UsdGeom.Scope.Define(stage, shadersPath)
            UsdGeom.Scope.Define(stage, materialsPath)
            # .. and as we create each surface, bind the associated material's variant to it
            allMaterials = []
            for material in materialBases:
                materialPrim = UsdShade.Material.Define(
                    stage, MakeMaterialPath(material))
                allMaterials.append(materialPrim.GetPrim())
                for variant in shadeVariations:
                    surface = UsdShade.Shader.Define(
                        stage, MakeSurfacePath(material, variant))
                    colorOut = surface.CreateOutput("out",
                                                    Sdf.ValueTypeNames.Color3f)

                    disp = UsdShade.Shader.Define(
                        stage, MakeDisplacementPath(material, variant))
                    dispOut = disp.CreateOutput('out',
                                                Sdf.ValueTypeNames.Vector3f)

                    pattern = UsdShade.Shader.Define(
                        stage, MakePatternPath(material, variant))
                    patternOut = pattern.CreateOutput(
                        "out", Sdf.ValueTypeNames.FloatArray)

                    with materialPrim.GetEditContextForVariant(variant):
                        surfaceOutput = materialPrim.CreateOutput(
                            "surf", colorOut.GetTypeName())
                        surfaceOutput.ConnectToSource(
                            UsdShade.ConnectionSourceInfo(
                                UsdShade.ConnectableAPI(colorOut.GetPrim()),
                                colorOut.GetBaseName(),
                                UsdShade.AttributeType.Output))

                        displacementOutput = materialPrim.CreateOutput(
                            "disp", dispOut.GetTypeName())
                        displacementOutput.ConnectToSource(dispOut)

                        patternOutput = materialPrim.CreateOutput(
                            "pattern", patternOut.GetTypeName())
                        patternOutput.ConnectToSource(patternOut)

            return allMaterials
示例#16
0
    def CheckPrim(self, prim):
        from pxr import UsdShade, Gf
        from pxr.UsdShade import Utils as ShadeUtils

        if not prim.IsA(UsdShade.Shader):
            return

        shader = UsdShade.Shader(prim)
        if not shader:
            self._AddError("Invalid shader prim <%s>." % prim.GetPath())
            return

        shaderId = self._GetShaderId(shader)

        # We may have failed to fetch an identifier for asset/source-based
        # nodes. We are only interested in UsdPreviewSurface nodes identified via
        # info:id, so it's not an error
        if not shaderId or shaderId != NodeTypes.UsdPreviewSurface:
            return

        normalInput = shader.GetInput(ShaderProps.Normal)
        if not normalInput:
            return
        valueProducingAttrs = ShadeUtils.GetValueProducingAttributes(
            normalInput)
        if not valueProducingAttrs or valueProducingAttrs[0].GetPrim() == prim:
            return

        sourcePrim = valueProducingAttrs[0].GetPrim()

        sourceShader = UsdShade.Shader(sourcePrim)
        if not sourceShader:
            # In theory, could be connected to an interface attribute of a
            # parent connectable... not useful, but not an error
            if UsdShade.ConnectableAPI(sourcePrim):
                return
            self._AddFailedCheck("%s.%s on prim <%s> is connected to a"
                                 " non-Shader prim." % \
                                 (NodeTypes.UsdPreviewSurface,
                                  ShaderProps.Normal))
            return

        sourceId = self._GetShaderId(sourceShader)

        # We may have failed to fetch an identifier for asset/source-based
        # nodes. OR, we could potentially be driven by a UsdPrimvarReader,
        # in which case we'd have nothing to validate
        if not sourceId or sourceId != NodeTypes.UsdUVTexture:
            return

        texAsset = self._GetInputValue(sourceShader, ShaderProps.File)

        if not texAsset or not texAsset.resolvedPath:
            self._AddFailedCheck("%s prim <%s> has invalid or unresolvable "
                                 "inputs:file of @%s@" % \
                                 (NodeTypes.UsdUVTexture,
                                  sourcePrim.GetPath(),
                                  texAsset.path if texAsset else ""))
            return

        if not self._TextureIs8Bit(texAsset):
            # really nothing more is required for image depths > 8 bits,
            # which we assume FOR NOW, are floating point
            return

        if not self._GetInputValue(sourceShader, ShaderProps.SourceColorSpace):
            self._AddWarning("%s prim <%s> that reads Normal Map @%s@ may need "
                             "to set inputs:sourceColorSpace to 'raw' as some "
                             "8-bit image writers always indicate an SRGB "
                             "encoding." % \
                             (NodeTypes.UsdUVTexture,
                              sourcePrim.GetPath(),
                              texAsset.path))

        bias = self._GetInputValue(sourceShader, ShaderProps.Bias)

        scale = self._GetInputValue(sourceShader, ShaderProps.Scale)

        if not (bias and scale and isinstance(bias, Gf.Vec4f)
                and isinstance(scale, Gf.Vec4f)):
            # XXX This should be a failure, as it results in broken normal
            # maps in Storm and hdPrman, at least.  But for the same reason
            # as the shader-under-shader check, we cannot fail until at least
            # the major authoring tools have been updated.
            self._AddWarning("%s prim <%s> reads 8 bit Normal Map @%s@, "
                             "which requires that inputs:scale be set to "
                             "[2, 2, 2, 1] and inputs:bias be set to "
                             "[-1, -1, -1, 0] for proper interpretation." %\
                             (NodeTypes.UsdUVTexture,
                              sourcePrim.GetPath(),
                              texAsset.path))
            return

        # don't really care about fourth components...
        if (bias[0] != -1 or bias[1] != -1 or bias[2] != -1 or scale[0] != 2
                or scale[1] != 2 or scale[2] != 2):
            self._AddWarning("%s prim <%s> reads an 8 bit Normal Map, "
                             "but has non-standard inputs:scale and "
                             "inputs:bias values of %s and %s" %\
                             (NodeTypes.UsdUVTexture,
                              sourcePrim.GetPath(),
                              str(scale), str(bias)))
示例#17
0
    def test_GetValueProducingAttribute(self):
        stage = Usd.Stage.Open('test.usda')

        material = UsdShade.ConnectableAPI(stage.GetPrimAtPath('/Material'))
        terminal = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/Terminal'))
        nodeGraph = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph'))
        nested1 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode1'))
        nested2 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode2'))
        superNested = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNodeGraph'
                                '/NestedNodeGraph2/SuperNestedNode'))

        # note, serval inputs resolve to the same attributes. Please see the
        # test.usda file to make sense of these connections

        # ----------------------------------------------------------------------
        # resolve top level inputs
        # ----------------------------------------------------------------------
        self._test(material, 'topLevelValue', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on terminal node
        # ----------------------------------------------------------------------
        self._test(terminal, 'terminalInput1', Output,
                   '/Material/NodeGraph/NestedNode1.outputs:nestedOut1')

        self._test(terminal, 'terminalInput2', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(terminal, 'terminalInput3', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(terminal, 'terminalInput4', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        self._test(
            terminal, 'terminalInput5', Output,
            '/Material/NodeGraph/NestedNodeGraph/NestedNodeGraph2'
            '/SuperNestedNode.outputs:superNestedOut')

        self._test(terminal, 'terminalInput6', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on node graph node
        # ----------------------------------------------------------------------
        self._test(nodeGraph, 'nodeGraphVal', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(nodeGraph, 'nodeGraphIn1', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(nodeGraph, 'nodeGraphIn2', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on nested nodes
        # ----------------------------------------------------------------------
        self._test(nested1, 'nestedIn1', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(nested2, 'nestedIn2', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(superNested, 'superNestedIn', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        # ----------------------------------------------------------------------
        # resolve invalid inputs
        # ----------------------------------------------------------------------
        self._testInvalid(terminal, 'terminalInput7')
        self._testInvalid(terminal, 'terminalInput8')

        # ----------------------------------------------------------------------
        # resolve inputs with a cycle
        # ----------------------------------------------------------------------
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:cycleA
        self._testInvalid(nodeGraph, 'cycleA')
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:deepCycleA
        self._testInvalid(nodeGraph, 'deepCycleA')
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:selfLoop
        self._testInvalid(nodeGraph, 'selfLoop')

        # ----------------------------------------------------------------------
        # resolve multi-connection inputs
        # ----------------------------------------------------------------------
        self._testMulti(terminal, 'multiInput1', [Output, Output], [
            '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
            '/Material/RegularNode.outputs:nodeOutput'
        ])
        self._testMulti(terminal, 'multiInput2', [Output, Output], [
            '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
            '/Material/NodeGraph/NestedNode2.outputs:nestedOut2'
        ])
        self._testMulti(
            terminal, 'multiInput3', [Input, Output, Output, Output], [
                '/Material/NodeGraph.inputs:nodeGraphVal',
                '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
                '/Material/NodeGraph/NestedNode2.outputs:nestedOut2',
                '/Material/RegularNode.outputs:nodeOutput'
            ], ['NodeGraphValue', None, None, None])
示例#18
0
    def testVarnameMerging(self):
        """
        Test that we produce a minimal number of UV readers and varname/varnameStr and that the
        connections are properly propagated across nodegraph boundaries.
        """
        cmds.file(f=True, new=True)

        # Use a namespace, for testing name sanitization...
        cmds.namespace(add="M")
        cmds.namespace(set="M")

        sphere_xform = cmds.polySphere()[0]

        material_node = cmds.shadingNode("usdPreviewSurface", asShader=True,
                                            name="ss01")
        material_sg = cmds.sets(renderable=True, noSurfaceShader=True,
                                empty=True, name="ss01SG")
        cmds.connectAttr(material_node+".outColor",
                            material_sg+".surfaceShader", force=True)
        cmds.sets(sphere_xform, e=True, forceElement=material_sg)

        # One file with UVs connected to diffuse:
        file_node = cmds.shadingNode("file", asTexture=True,
                                     isColorManaged=True)
        uv_node = cmds.shadingNode("place2dTexture", asUtility=True)
        cmds.setAttr(uv_node + ".offsetU", 0.125)
        cmds.setAttr(uv_node + ".offsetV", 0.5)
        connectUVNode(uv_node, file_node)
        cmds.connectAttr(file_node + ".outColor",
                         material_node + ".diffuseColor", f=True)

        # Another file, same UVs, connected to emissiveColor
        file_node = cmds.shadingNode("file", asTexture=True,
                                     isColorManaged=True)
        connectUVNode(uv_node, file_node)
        cmds.connectAttr(file_node + ".outColor",
                         material_node + ".emissiveColor", f=True)

        # Another file, no UVs, connected to metallic
        file_node = cmds.shadingNode("file", asTexture=True,
                                     isColorManaged=True)
        cmds.connectAttr(file_node + ".outColorR",
                         material_node + ".metallic", f=True)

        # Another file, no UVs, connected to roughness
        file_node = cmds.shadingNode("file", asTexture=True,
                                     isColorManaged=True)
        cmds.connectAttr(file_node + ".outColorR",
                         material_node + ".roughness", f=True)
        cmds.setAttr(file_node + ".offsetU", 0.25)
        cmds.setAttr(file_node + ".offsetV", 0.75)

        # Export to USD:
        usd_path = os.path.abspath('MinimalUVReader.usda')
        cmds.usdExport(mergeTransformAndShape=True,
            file=usd_path,
            shadingMode='useRegistry',
            convertMaterialsTo=['MaterialX', 'UsdPreviewSurface'])

        # We expect 2 primvar readers, and 2 st transforms:
        stage = Usd.Stage.Open(usd_path)
        mat_path = "/M_pSphere1/Looks/M_ss01SG"

        # Here are the expected connections in the produced USD file:
        connections = [
            # UsdPreviewSurface section

            # Source node, input, destination node:
            ("/UsdPreviewSurface/M_ss01", "diffuseColor", "/UsdPreviewSurface/M_file1"),
            ("/UsdPreviewSurface/M_file1", "st", "/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d"),
            ("/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d", "in", "/UsdPreviewSurface/M_place2dTexture1"),

            ("/UsdPreviewSurface/M_ss01", "emissiveColor", "/UsdPreviewSurface/M_file2"),
            ("/UsdPreviewSurface/M_file2", "st", "/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d"), # re-used
            # Note that the transform name is derived from place2DTexture name.

            ("/UsdPreviewSurface/M_ss01", "metallic", "/UsdPreviewSurface/M_file3"),
            ("/UsdPreviewSurface/M_file3", "st", "/UsdPreviewSurface/shared_TexCoordReader"), # no UV in Maya.

            ("/UsdPreviewSurface/M_ss01", "roughness", "/UsdPreviewSurface/M_file4"),
            ("/UsdPreviewSurface/M_file4", "st", "/UsdPreviewSurface/M_file4_UsdTransform2d"), # xform on file node
            ("/UsdPreviewSurface/M_file4_UsdTransform2d", "in", "/UsdPreviewSurface/shared_TexCoordReader"),
            # Note that the transform name is derived from file node name.

            # MaterialX section

            # Source node, input, destination node:
            ("/MaterialX/MayaNG_MaterialX", "diffuseColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file1_rgb"),
            ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file1_rgb", "in", "/MaterialX/MayaNG_MaterialX/M_file1"),
            ("/MaterialX/MayaNG_MaterialX/M_file1", "texcoord", "/MaterialX/MayaNG_MaterialX/M_place2dTexture1"),

            ("/MaterialX/MayaNG_MaterialX", "emissiveColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file2_rgb"),
            ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file2_rgb", "in", "/MaterialX/MayaNG_MaterialX/M_file2"),
            ("/MaterialX/MayaNG_MaterialX/M_file2", "texcoord", "/MaterialX/MayaNG_MaterialX/M_place2dTexture1"), # re-used

            ("/MaterialX/MayaNG_MaterialX", "metallic", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file3_r"),
            ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file3_r", "in", "/MaterialX/MayaNG_MaterialX/M_file3"),
            ("/MaterialX/MayaNG_MaterialX/M_file3", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # no UV in Maya.

            ("/MaterialX/MayaNG_MaterialX", "roughness", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file4_r"),
            ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file4_r", "in", "/MaterialX/MayaNG_MaterialX/M_file4"),
            ("/MaterialX/MayaNG_MaterialX/M_file4", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # re-used

            # Making sure no NodeGraph boundaries were skipped downstream:
            ("", "surface", "/UsdPreviewSurface"),
            ("/UsdPreviewSurface", "surface", "/UsdPreviewSurface/M_ss01"),

            ("", "mtlx:surface", "/MaterialX"),
            ("/MaterialX", "surface", "/MaterialX/M_ss01"),

            # Making sure no NodeGraph boundaries were skipped upstream:
            ("/UsdPreviewSurface/M_place2dTexture1", "varname", "/UsdPreviewSurface"),
            ("/UsdPreviewSurface", "M:file1:varname", ""),

            ("/MaterialX/MayaNG_MaterialX/M_place2dTexture1", "geomprop", "/MaterialX/MayaNG_MaterialX"),
            ("/MaterialX/MayaNG_MaterialX", "M:file1:varnameStr", "/MaterialX"),
            ("/MaterialX", "M:file1:varnameStr", ""),
        ]
        for src_name, input_name, dst_name in connections:
            src_prim = stage.GetPrimAtPath(mat_path + src_name)
            self.assertTrue(src_prim, mat_path + src_name + " does not exist")
            src_shade = UsdShade.ConnectableAPI(src_prim)
            self.assertTrue(src_shade)
            src_input = src_shade.GetInput(input_name)
            if not src_input:
                src_input = src_shade.GetOutput(input_name)
            self.assertTrue(src_input, input_name + " does not exist on " + mat_path + src_name)
            self.assertTrue(src_input.HasConnectedSource(), input_name + " does not have source")
            (connect_api, out_name, _) = src_input.GetConnectedSource()
            self.assertEqual(connect_api.GetPath(), mat_path + dst_name)
    def test_GetValueProducingAttribute(self):
        stage = Usd.Stage.Open('test.usda')

        material = UsdShade.ConnectableAPI(stage.GetPrimAtPath('/Material'))
        terminal = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/Terminal'))
        nodeGraph = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph'))
        nested1 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode1'))
        nested2 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode2'))
        superNested = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNodeGraph'
                                '/NestedNodeGraph2/SuperNestedNode'))

        # note, serval inputs resolve to the same attributes. Please see the
        # test.usda file to make sense of these connections

        # ----------------------------------------------------------------------
        # resolve top level inputs
        # ----------------------------------------------------------------------
        self._test(material, 'topLevelValue', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on terminal node
        # ----------------------------------------------------------------------
        self._test(terminal, 'terminalInput1', Output,
                   '/Material/NodeGraph/NestedNode1.outputs:nestedOut1')

        self._test(terminal, 'terminalInput2', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(terminal, 'terminalInput3', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(terminal, 'terminalInput4', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        self._test(
            terminal, 'terminalInput5', Output,
            '/Material/NodeGraph/NestedNodeGraph/NestedNodeGraph2'
            '/SuperNestedNode.outputs:superNestedOut')

        self._test(terminal, 'terminalInput6', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on node graph node
        # ----------------------------------------------------------------------
        self._test(nodeGraph, 'nodeGraphVal', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(nodeGraph, 'nodeGraphIn1', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(nodeGraph, 'nodeGraphIn2', Input,
                   '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on nested nodes
        # ----------------------------------------------------------------------
        self._test(nested1, 'nestedIn1', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        self._test(nested2, 'nestedIn2', Output,
                   '/Material/RegularNode.outputs:nodeOutput')

        self._test(superNested, 'superNestedIn', Input,
                   '/Material/NodeGraph.inputs:nodeGraphVal', 'NodeGraphValue')

        # ----------------------------------------------------------------------
        # resolve invalid inputs
        # ----------------------------------------------------------------------
        self._testInvalid(terminal, 'terminalInput7')
        self._testInvalid(terminal, 'terminalInput8')

        # ----------------------------------------------------------------------
        # resolve inputs with a cycle
        # ----------------------------------------------------------------------
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:cycleA
        self._testInvalid(nodeGraph, 'cycleA')
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:deepCycleA
        self._testInvalid(nodeGraph, 'deepCycleA')
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:selfLoop
        self._testInvalid(nodeGraph, 'selfLoop')

        # ----------------------------------------------------------------------
        # resolve multi-connection inputs
        # ----------------------------------------------------------------------
        self._testMulti(terminal, 'multiInput1', [Output, Output], [
            '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
            '/Material/RegularNode.outputs:nodeOutput'
        ])
        self._testMulti(terminal, 'multiInput2', [Output, Output], [
            '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
            '/Material/NodeGraph/NestedNode2.outputs:nestedOut2'
        ])
        self._testMulti(
            terminal, 'multiInput3', [Input, Output, Output, Output], [
                '/Material/NodeGraph.inputs:nodeGraphVal',
                '/Material/NodeGraph/NestedNode1.outputs:nestedOut1',
                '/Material/NodeGraph/NestedNode2.outputs:nestedOut2',
                '/Material/RegularNode.outputs:nodeOutput'
            ], ['NodeGraphValue', None, None, None])

        # ----------------------------------------------------------------------
        # test resolution with the shaderOutputsOnly=True mode
        # ----------------------------------------------------------------------
        # Test Outputs
        # Finding the upstream attribute that is an output on a shader
        surfaceGood = material.GetOutput('surfaceGood')
        attrs = UsdShade.Utils.GetValueProducingAttributes(
            surfaceGood, shaderOutputsOnly=True)
        self.assertEqual(len(attrs), 1)
        self.assertEqual(attrs[0].GetPath(),
                         Sdf.Path('/Material/Terminal.outputs:bxdfOut'))

        # Make sure it does not find upstream attributes that are not shader
        # outputs and carry values
        surfaceBad = material.GetOutput('surfaceBad')
        attrs = UsdShade.Utils.GetValueProducingAttributes(
            surfaceBad, shaderOutputsOnly=True)
        self.assertEqual(attrs, [])

        # Test Inputs
        # Finding the upstream attribute that is an output of a shader
        inputGood = terminal.GetInput('terminalInput1')
        attrs = UsdShade.Utils.GetValueProducingAttributes(
            inputGood, shaderOutputsOnly=True)
        self.assertEqual(len(attrs), 1)
        self.assertEqual(
            attrs[0].GetPath(),
            Sdf.Path('/Material/NodeGraph/NestedNode1.outputs:nestedOut1'))

        # Make sure it does not find upstream attributes that are not shader
        # outputs and carry values
        inputBad = terminal.GetInput('terminalInput2')
        attrs = UsdShade.Utils.GetValueProducingAttributes(
            inputBad, shaderOutputsOnly=True)
        self.assertEqual(attrs, [])
示例#20
0
def _bugStep3(s):
    # change diffuse texture
    diffuseTextureSampler = UsdShade.ConnectableAPI(s.GetPrimAtPath('/Scene/Looks/NewMaterial/Texture'))
    diffuseTextureSampler.CreateInput('file', Sdf.ValueTypeNames.Asset).Set("test2.png")
    def test_GetValueProducingAttribute(self):
        stage = Usd.Stage.Open('test.usda')

        material = UsdShade.ConnectableAPI(stage.GetPrimAtPath('/Material'))
        terminal = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/Terminal'))
        nodeGraph = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph'))
        nested1 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode1'))
        nested2 = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNode2'))
        superNested = UsdShade.ConnectableAPI(
            stage.GetPrimAtPath('/Material/NodeGraph/NestedNodeGraph'
                                '/NestedNodeGraph2/SuperNestedNode'))

        # note, serval inputs resolve to the same attributes. Please see the
        # test.usda file to make sense of these connections

        # ----------------------------------------------------------------------
        # resolve top level inputs
        # ----------------------------------------------------------------------
        attr, attrType = \
            material.GetInput('topLevelValue').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on terminal node
        # ----------------------------------------------------------------------
        attr, attrType = \
            terminal.GetInput('terminalInput1').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Output)
        self._check(attr, '/Material/NodeGraph/NestedNode1.outputs:nestedOut1')

        attr, attrType = \
            terminal.GetInput('terminalInput2').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material/NodeGraph.inputs:nodeGraphVal',
                    'NodeGraphValue')

        attr, attrType = \
            terminal.GetInput('terminalInput3').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Output)
        self._check(attr, '/Material/RegularNode.outputs:nodeOutput')

        attr, attrType = \
            terminal.GetInput('terminalInput4').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material.inputs:topLevelValue', 'TopLevelValue')

        attr, attrType = \
            terminal.GetInput('terminalInput5').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Output)
        self._check(
            attr, '/Material/NodeGraph/NestedNodeGraph/NestedNodeGraph2'
            '/SuperNestedNode.outputs:superNestedOut')

        attr, attrType = \
            terminal.GetInput('terminalInput6').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on node graph node
        # ----------------------------------------------------------------------
        attr, attrType = \
            nodeGraph.GetInput('nodeGraphVal').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material/NodeGraph.inputs:nodeGraphVal',
                    'NodeGraphValue')

        attr, attrType = \
            nodeGraph.GetInput('nodeGraphIn1').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Output)
        self._check(attr, '/Material/RegularNode.outputs:nodeOutput')

        attr, attrType = \
            nodeGraph.GetInput('nodeGraphIn2').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material.inputs:topLevelValue', 'TopLevelValue')

        # ----------------------------------------------------------------------
        # resolve inputs on nested nodes
        # ----------------------------------------------------------------------
        attr, attrType = \
            nested1.GetInput('nestedIn1').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material/NodeGraph.inputs:nodeGraphVal',
                    'NodeGraphValue')

        attr, attrType = \
            nested2.GetInput('nestedIn2').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Output)
        self._check(attr, '/Material/RegularNode.outputs:nodeOutput')

        attr, attrType = \
            superNested.GetInput('superNestedIn').GetValueProducingAttribute()
        self.assertEqual(attrType, UsdShade.AttributeType.Input)
        self._check(attr, '/Material/NodeGraph.inputs:nodeGraphVal',
                    'NodeGraphValue')

        # ----------------------------------------------------------------------
        # resolve invalid inputs
        # ----------------------------------------------------------------------
        attr, attrType = \
            terminal.GetInput('terminalInput7').GetValueProducingAttribute()
        self.assertFalse(attr)
        self.assertEqual(attrType, UsdShade.AttributeType.Invalid)
        attr, attrType = \
            terminal.GetInput('terminalInput8').GetValueProducingAttribute()
        self.assertFalse(attr)
        self.assertEqual(attrType, UsdShade.AttributeType.Invalid)

        # ----------------------------------------------------------------------
        # resolve inputs with a cycle
        # ----------------------------------------------------------------------
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:cycleA
        attr, attrType = \
            nodeGraph.GetInput('cycleA').GetValueProducingAttribute()
        self.assertFalse(attr)
        self.assertEqual(attrType, UsdShade.AttributeType.Invalid)
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:deepCycleA
        attr, attrType = \
            nodeGraph.GetInput('deepCycleA').GetValueProducingAttribute()
        self.assertFalse(attr)
        self.assertEqual(attrType, UsdShade.AttributeType.Invalid)
        # This will issue a warning (TF_WARN):
        # GetValueProducingAttribute:
        #    Found cycle with attribute /Material/NodeGraph.inputs:selfLoop
        attr, attrType = \
            nodeGraph.GetInput('selfLoop').GetValueProducingAttribute()
        self.assertFalse(attr)
        self.assertEqual(attrType, UsdShade.AttributeType.Invalid)
示例#22
0
    def test_Basic(self):
        MaterialPath = Sdf.Path("/Material")
        ShaderPath = Sdf.Path("/Material/Shader")
        NodeGraphPath = Sdf.Path("/Material/NodeGraph")
        NestedShaderPath = Sdf.Path("/Material/NodeGraph/NestedShader")

        usdStage = Usd.Stage.CreateInMemory()
        self.assertTrue(usdStage)

        material = UsdShade.Material.Define(usdStage, MaterialPath)
        self.assertTrue(material)
        self.assertTrue(UsdShade.ConnectableAPI(material).IsContainer())

        nodeGraph = UsdShade.NodeGraph.Define(usdStage, NodeGraphPath)
        self.assertTrue(nodeGraph)
        self.assertTrue(UsdShade.ConnectableAPI(nodeGraph).IsContainer())
        self.assertTrue(UsdShade.ConnectableAPI(nodeGraph).IsNodeGraph())

        shader = UsdShade.Shader.Define(usdStage, ShaderPath)
        self.assertTrue(shader)
        self.assertFalse(UsdShade.ConnectableAPI(shader).IsContainer())
        self.assertTrue(UsdShade.ConnectableAPI(shader).IsShader())

        nestedShader = UsdShade.Shader.Define(usdStage, NestedShaderPath)
        self.assertTrue(nestedShader)

        # Create all inputs and connections.

        # Create a float interface input on the material.
        matConnectable = material.ConnectableAPI()
        floatInterfaceInput = matConnectable.CreateInput(
            "floatInput", Sdf.ValueTypeNames.Float)
        # default connectability of an interface-input is 'full'
        self.assertEqual(floatInterfaceInput.GetConnectability(),
                         UsdShade.Tokens.full)
        # inputs on a material are not connectable
        xAttr = material.GetPrim().CreateAttribute("x",
                                                   Sdf.ValueTypeNames.Double,
                                                   True)
        self._CanConnect(floatInterfaceInput, xAttr)

        self.assertTrue(
            floatInterfaceInput.SetConnectability(
                UsdShade.Tokens.interfaceOnly))
        self.assertEqual(floatInterfaceInput.GetConnectability(),
                         UsdShade.Tokens.interfaceOnly)

        self.assertTrue(floatInterfaceInput.ClearConnectability())
        self.assertEqual(floatInterfaceInput.GetConnectability(),
                         UsdShade.Tokens.full)

        # Create a color valued interface input on the material.
        colorInterfaceInput = material.CreateInput("colorInput",
                                                   Sdf.ValueTypeNames.Color3f)
        self.assertEqual(colorInterfaceInput.GetConnectability(),
                         UsdShade.Tokens.full)
        self.assertTrue(
            colorInterfaceInput.SetConnectability(
                UsdShade.Tokens.interfaceOnly))

        colorMaterialOutput = material.CreateOutput("colorOutput",
                                                    Sdf.ValueTypeNames.Color3f)

        # Create shader inputs.
        shaderConnectable = shader.ConnectableAPI()
        shaderInputFloat = shaderConnectable.CreateInput(
            "shaderFloat", Sdf.ValueTypeNames.Float)
        shaderInputColor = shader.CreateInput("shaderColor",
                                              Sdf.ValueTypeNames.Color3f)
        self.assertEqual(shaderInputFloat.GetConnectability(),
                         UsdShade.Tokens.full)
        self.assertEqual(shaderInputColor.GetConnectability(),
                         UsdShade.Tokens.full)

        # The shader inputs have full connectability by default and can be
        # connected to any input or output.
        self._CanConnect(shaderInputColor, colorInterfaceInput)
        # Make the connection.
        self.assertTrue(
            shaderInputColor.ConnectToSource(
                UsdShade.ConnectionSourceInfo(
                    material, colorInterfaceInput.GetBaseName(),
                    UsdShade.AttributeType.Input)))

        self.assertEqual(shaderInputColor.GetAttr().GetConnections(),
                         [colorInterfaceInput.GetAttr().GetPath()])

        self._CanConnect(shaderInputFloat, floatInterfaceInput)
        self.assertTrue(shaderInputFloat.ConnectToSource(floatInterfaceInput))

        self.assertEqual(shaderInputFloat.GetAttr().GetConnections(),
                         [floatInterfaceInput.GetAttr().GetPath()])

        shaderOutputColor = shader.CreateOutput("color",
                                                Sdf.ValueTypeNames.Color3f)
        shaderOutputFloat = shader.CreateOutput("fOut",
                                                Sdf.ValueTypeNames.Float)

        nodeGraphInputFloat = nodeGraph.CreateInput("nodeGraphFlIn",
                                                    Sdf.ValueTypeNames.Float)
        self.assertEqual(nodeGraphInputFloat.GetConnectability(),
                         UsdShade.Tokens.full)

        # NodeGraph Input with "interfaceOnly" connectability cannot be
        # connected to an output.
        self.assertTrue(
            nodeGraphInputFloat.SetConnectability(
                UsdShade.Tokens.interfaceOnly))
        self._CannotConnect(nodeGraphInputFloat, shaderOutputFloat)

        # NodeGraph Input with full connectability can be connected to an output.
        self.assertTrue(
            nodeGraphInputFloat.SetConnectability(UsdShade.Tokens.full))
        self._CanConnect(nodeGraphInputFloat, shaderOutputFloat)
        self.assertTrue(
            nodeGraphInputFloat.ConnectToSource(
                UsdShade.ConnectionSourceInfo(shaderOutputFloat)))

        nodeGraphInputColor = nodeGraph.CreateInput("nodeGraphColor",
                                                    Sdf.ValueTypeNames.Color3f)
        self.assertTrue(
            nodeGraphInputColor.SetConnectability(
                UsdShade.Tokens.interfaceOnly))
        # Can't connect an "interfaceOnly" input to an output on a shader or node-graph.
        self._CannotConnect(nodeGraphInputColor, shaderOutputColor)
        self._CannotConnect(nodeGraphInputColor, colorMaterialOutput)

        # Can't connect an "interfaceOnly" input to a "full" input on a shader.
        self._CannotConnect(nodeGraphInputColor, shaderInputColor)

        # Change connectability of input on shader to "interfaceOnly" to allow the
        # previously attempted connection.
        self.assertTrue(
            shaderInputColor.SetConnectability(UsdShade.Tokens.interfaceOnly))
        self._CanConnect(nodeGraphInputColor, shaderInputColor)
        self.assertTrue(
            nodeGraphInputColor.SetConnectedSources(
                [UsdShade.ConnectionSourceInfo(shaderInputColor)]))

        # Change connectability of an interface input to full, to test connection
        # from an "interfaceOnly" to a "full" input on a nodegraph.
        self.assertTrue(
            floatInterfaceInput.SetConnectability(UsdShade.Tokens.full))
        self.assertEqual(floatInterfaceInput.GetConnectability(),
                         UsdShade.Tokens.full)

        nestedShaderInputFloat = nestedShader.CreateInput(
            "nestedShaderFloat", Sdf.ValueTypeNames.Float)
        self.assertTrue(
            nestedShaderInputFloat.SetConnectability(
                UsdShade.Tokens.interfaceOnly))
        self._CannotConnect(nestedShaderInputFloat, floatInterfaceInput)

        # Change connectability of interface input to "interfaceOnly". This will
        # allow the previously attempted connection.
        self.assertTrue(
            floatInterfaceInput.SetConnectability(
                UsdShade.Tokens.interfaceOnly))
        self._CanConnect(nestedShaderInputFloat, floatInterfaceInput)
        self.assertTrue(
            nestedShaderInputFloat.ConnectToSource(floatInterfaceInput))

        # Test the ability to connect to multiple sources
        floatInterfaceInput2 = matConnectable.CreateInput(
            "floatInput2", Sdf.ValueTypeNames.Float)
        self.assertTrue(
            shaderInputFloat.ConnectToSource(
                UsdShade.ConnectionSourceInfo(floatInterfaceInput2),
                UsdShade.ConnectionModification.Append))
        self.assertEqual(shaderInputFloat.GetAttr().GetConnections(), [
            floatInterfaceInput.GetAttr().GetPath(),
            floatInterfaceInput2.GetAttr().GetPath()
        ])

        floatInterfaceInput3 = matConnectable.CreateInput(
            "floatInput3", Sdf.ValueTypeNames.Float)
        self.assertTrue(
            shaderInputFloat.ConnectToSource(
                UsdShade.ConnectionSourceInfo(floatInterfaceInput3),
                UsdShade.ConnectionModification.Prepend))
        self.assertEqual(shaderInputFloat.GetAttr().GetConnections(), [
            floatInterfaceInput3.GetAttr().GetPath(),
            floatInterfaceInput.GetAttr().GetPath(),
            floatInterfaceInput2.GetAttr().GetPath()
        ])

        sourceInfos, invalidPaths = shaderInputFloat.GetConnectedSources()
        self.assertEqual(sourceInfos, [
            UsdShade.ConnectionSourceInfo(floatInterfaceInput3),
            UsdShade.ConnectionSourceInfo(floatInterfaceInput),
            UsdShade.ConnectionSourceInfo(floatInterfaceInput2)
        ])
        self.assertEqual(invalidPaths, [])

        # Test the targeted disconnection of a single source
        shaderInputFloat.DisconnectSource(floatInterfaceInput.GetAttr())
        sourceInfos, invalidPaths = shaderInputFloat.GetConnectedSources()
        self.assertEqual(sourceInfos, [
            UsdShade.ConnectionSourceInfo(floatInterfaceInput3),
            UsdShade.ConnectionSourceInfo(floatInterfaceInput2)
        ])
        self.assertEqual(invalidPaths, [])

        # Calling DisconnectSource without a specific source attribute will
        # remove all remaining connections
        shaderInputFloat.DisconnectSource()
        sourceInfos, invalidPaths = shaderInputFloat.GetConnectedSources()
        self.assertEqual(sourceInfos, [])
        self.assertEqual(invalidPaths, [])

        # Clear sources is another way to remove all connections
        shaderInputColor.ClearSources()
        sourceInfos, invalidPaths = shaderInputColor.GetConnectedSources()
        self.assertEqual(sourceInfos, [])
        self.assertEqual(invalidPaths, [])