| 336 | } // namespace |
| 337 | |
| 338 | void ShaderNetworkAlgo::addComponentConnectionAdapters( ShaderNetwork *network, std::string targetPrefix ) |
| 339 | { |
| 340 | // Output parameters |
| 341 | |
| 342 | using ParameterMap = std::unordered_map<ShaderNetwork::Parameter, ShaderNetwork::Parameter>; |
| 343 | ParameterMap outputConversions; |
| 344 | for( const auto &s : network->shaders() ) |
| 345 | { |
| 346 | ShaderNetwork::ConnectionRange inputConnections = network->inputConnections( s.first ); |
| 347 | for( ShaderNetwork::ConnectionIterator it = inputConnections.begin(); it != inputConnections.end(); ) |
| 348 | { |
| 349 | // Copy and increment now so we still have a valid iterator |
| 350 | // if we remove the connection. |
| 351 | const ShaderNetwork::Connection connection = *it++; |
| 352 | |
| 353 | const Shader *sourceShader = network->getShader( connection.source.shader ); |
| 354 | if( !boost::starts_with( sourceShader->getType(), targetPrefix ) ) |
| 355 | { |
| 356 | continue; |
| 357 | } |
| 358 | |
| 359 | boost::cmatch match; |
| 360 | if( boost::regex_match( connection.source.name.c_str(), match, g_componentRegex ) ) |
| 361 | { |
| 362 | // Insert a conversion shader to handle connection from component. |
| 363 | auto inserted = outputConversions.insert( { connection.source, ShaderNetwork::Parameter() } ); |
| 364 | if( inserted.second ) |
| 365 | { |
| 366 | InternedString component = match[2].str(); |
| 367 | const SplitAdapter &adapter = findSplitAdapter( sourceShader->getType(), component ); |
| 368 | |
| 369 | ShaderPtr adapterShader = adapter.shader->copy(); |
| 370 | adapterShader->blindData()->writable()[g_splitAdapterComponent] = new InternedStringData( component ); |
| 371 | adapterShader->blindData()->writable()[g_splitAdapterInParameter] = new InternedStringData( adapter.inParameter ); |
| 372 | adapterShader->blindData()->writable()[g_splitAdapterOutParameter] = new InternedStringData( adapter.outParameter ); |
| 373 | |
| 374 | const InternedString adapterHandle = network->addShader( g_splitAdapterHandle, std::move( adapterShader ) ); |
| 375 | network->addConnection( ShaderNetwork::Connection( |
| 376 | ShaderNetwork::Parameter{ connection.source.shader, InternedString( match[1] ) }, |
| 377 | ShaderNetwork::Parameter{ adapterHandle, adapter.inParameter } |
| 378 | ) ); |
| 379 | inserted.first->second = { adapterHandle, adapter.outParameter }; |
| 380 | } |
| 381 | network->removeConnection( connection ); |
| 382 | network->addConnection( { inserted.first->second, connection.destination } ); |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | // Input parameters |
| 388 | |
| 389 | std::unordered_set<InternedString> convertedParameters; |
| 390 | for( const auto &shader : network->shaders() ) |
| 391 | { |
| 392 | if( !boost::starts_with( shader.second->getType(), targetPrefix ) ) |
| 393 | { |
| 394 | continue; |
| 395 | } |