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())
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()))
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())
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())
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')))
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
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
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)))
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])
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, [])
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)
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, [])