@@ -53,6 +53,8 @@ namespace
5353
5454pxr::TfToken g_adapterLabelToken ( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel().string() );
5555
56+ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk ( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork );
57+
5658IECore::InternedString readShaderNetworkWalk ( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork )
5759{
5860 IECore::InternedString handle ( usdShader.GetPath ().MakeRelativePath ( anchorPath ).GetString () );
@@ -84,8 +86,7 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
8486
8587 IECore::CompoundDataPtr parametersData = new IECore::CompoundData ();
8688 IECore::CompoundDataMap ¶meters = parametersData->writable ();
87- std::vector< std::tuple< IECore::InternedString, pxr::UsdShadeConnectableAPI, IECore::InternedString > > connections;
88- std::vector< pxr::UsdShadeInput > inputs = usdShader.GetInputs ();
89+ std::vector<IECoreScene::ShaderNetwork::Connection> connections;
8990 for ( pxr::UsdShadeInput &i : usdShader.GetInputs () )
9091 {
9192 pxr::UsdShadeConnectableAPI usdSource;
@@ -95,9 +96,14 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
9596 pxr::UsdAttribute valueAttribute = i;
9697 if ( i.GetConnectedSource ( &usdSource, &usdSourceName, &usdSourceType ) )
9798 {
98- if ( !usdSource. IsContainer () )
99+ if ( usdSourceType == pxr::UsdShadeAttributeType::Output )
99100 {
100- connections.push_back ( { i.GetBaseName ().GetString (), usdSource, usdSourceName.GetString () } );
101+ const IECoreScene::ShaderNetwork::Parameter sourceHandle = readShaderNetworkWalk (
102+ anchorPath, usdSource.GetOutput ( usdSourceName ), shaderNetwork
103+ );
104+ connections.push_back ( {
105+ sourceHandle, { handle, IECore::InternedString ( i.GetBaseName ().GetString () ) }
106+ } );
101107 }
102108 else
103109 {
@@ -124,33 +130,28 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
124130 }
125131 shaderNetwork.addShader ( handle, std::move ( newShader ) );
126132
133+ // Can only add connections after we've added the shader.
127134 for ( const auto &c : connections )
128135 {
129- IECore::InternedString attributeName;
130- pxr::UsdShadeConnectableAPI usdSource;
131- IECore::InternedString sourceAttributeName;
132- std::tie ( attributeName, usdSource, sourceAttributeName ) = c;
133- IECore::InternedString sourceHandle = readShaderNetworkWalk ( anchorPath, pxr::UsdShadeShader ( usdSource.GetPrim () ), shaderNetwork );
134-
135- if ( sourceAttributeName == " DEFAULT_OUTPUT" )
136- {
137- shaderNetwork.addConnection ( IECoreScene::ShaderNetwork::Connection (
138- { sourceHandle, " " },
139- { handle, attributeName }
140- ) );
141- }
142- else
143- {
144- shaderNetwork.addConnection ( IECoreScene::ShaderNetwork::Connection (
145- { sourceHandle, sourceAttributeName },
146- { handle, attributeName }
147- ) );
148- }
136+ shaderNetwork.addConnection ( c );
149137 }
150138
151139 return handle;
152140}
153141
142+ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk ( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork )
143+ {
144+ IECore::InternedString shaderHandle = readShaderNetworkWalk ( anchorPath, pxr::UsdShadeShader ( output.GetPrim () ), shaderNetwork );
145+ if ( output.GetBaseName () != " DEFAULT_OUTPUT" )
146+ {
147+ return IECoreScene::ShaderNetwork::Parameter ( shaderHandle, output.GetBaseName ().GetString () );
148+ }
149+ else
150+ {
151+ return IECoreScene::ShaderNetwork::Parameter ( shaderHandle );
152+ }
153+ }
154+
154155} // namespace
155156
156157pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork ( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
@@ -249,10 +250,21 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene
249250 return networkOutUsd;
250251}
251252
252- IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork ( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &outputShader, const pxr::TfToken &outputParameter )
253+ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork ( const pxr::UsdShadeOutput &output )
253254{
255+ pxr::UsdShadeConnectableAPI usdSource;
256+ pxr::TfToken usdSourceName;
257+ pxr::UsdShadeAttributeType usdSourceType;
258+ if (
259+ !output.GetConnectedSource ( &usdSource, &usdSourceName, &usdSourceType ) ||
260+ usdSourceType != pxr::UsdShadeAttributeType::Output
261+ )
262+ {
263+ return new IECoreScene::ShaderNetwork ();
264+ }
265+
254266 IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork ();
255- IECore::InternedString outputHandle = readShaderNetworkWalk ( anchorPath, outputShader , *result );
267+ IECoreScene::ShaderNetwork::Parameter outputHandle = readShaderNetworkWalk ( usdSource. GetPrim (). GetParent (). GetPath (), usdSource. GetOutput ( usdSourceName ) , *result );
256268
257269 // For the output shader, set the type to "ai:surface" if it is "ai:shader".
258270 // This is complete nonsense - there is nothing to suggest that this shader is
@@ -265,22 +277,15 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
265277 // don't use the suffix of the shader type for anything, and we should just set
266278 // everything to prefix:shader ( aside from lights, which are a bit of a
267279 // different question )
268- if ( result->getShader ( outputHandle )->getType () == " ai:shader" )
280+ const IECoreScene::Shader *outputShader = result->getShader ( outputHandle.shader );
281+ if ( outputShader->getType () == " ai:shader" )
269282 {
270- IECoreScene::ShaderPtr o = result-> getShader ( outputHandle ) ->copy ();
283+ IECoreScene::ShaderPtr o = outputShader ->copy ();
271284 o->setType ( " ai:surface" );
272- result->setShader ( outputHandle, std::move ( o ) );
285+ result->setShader ( outputHandle. shader , std::move ( o ) );
273286 }
274287
275- // handles[0] is the handle of the first shader added, which is always the output shader
276- if ( outputParameter.GetString () != " DEFAULT_OUTPUT" )
277- {
278- result->setOutput ( IECoreScene::ShaderNetwork::Parameter ( outputHandle, outputParameter.GetString () ) );
279- }
280- else
281- {
282- result->setOutput ( IECoreScene::ShaderNetwork::Parameter ( outputHandle ) );
283- }
288+ result->setOutput ( outputHandle );
284289
285290 IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters ( result.get () );
286291
0 commit comments