static void loadShaderParameters( const OSLQuery &query, Gaffer::CompoundPlug *parametersPlug, bool keepExistingValues ) { // if we're not preserving existing values then remove all existing parameter plugs - the various // plug creators above know that if a plug exists then they should preserve its values. if( !keepExistingValues ) { parametersPlug->clearChildren(); } // make sure we have a plug to represent each parameter, reusing plugs wherever possible. set<string> validPlugNames; for( size_t i = 0; i < query.nparams(); ++i ) { const OSLQuery::Parameter *parameter = query.getparam( i ); const Plug::Direction direction = parameter->isoutput ? Plug::Out : Plug::In; if( direction != parametersPlug->direction() ) { continue; } if( parameter->name.find( "." ) != string::npos ) { // member of a struct - will be loaded when the struct is loaded continue; } const Plug *plug = loadShaderParameter( query, parameter, parametersPlug, keepExistingValues ); if( plug ) { validPlugNames.insert( parameter->name ); } } // remove any old plugs which it turned out we didn't need if( keepExistingValues ) { for( int i = parametersPlug->children().size() - 1; i >= 0; --i ) { GraphComponent *child = parametersPlug->getChild<GraphComponent>( i ); if( validPlugNames.find( child->getName().string() ) == validPlugNames.end() ) { parametersPlug->removeChild( child ); } } } }
static Plug *loadStructParameter( const OSLQuery &query, const OSLQuery::Parameter *parameter, Gaffer::CompoundPlug *parent, bool keepExistingValues ) { CompoundPlug *result = NULL; const string name = plugName( parameter ); CompoundPlug *existingPlug = parent->getChild<CompoundPlug>( name ); if( existingPlug ) { if( !keepExistingValues ) { existingPlug->clearChildren(); } result = existingPlug; } else { result = new CompoundPlug( name, parent->direction(), Plug::Default | Plug::Dynamic ); } for( vector<string>::const_iterator it = parameter->fields.begin(), eIt = parameter->fields.end(); it != eIt; ++it ) { std::string fieldName = parameter->name + "." + *it; loadShaderParameter( query, query.getparam( fieldName ), result, keepExistingValues ); } // remove any old plugs which it turned out we didn't need if( keepExistingValues ) { for( int i = result->children().size() - 1; i >= 0; --i ) { GraphComponent *child = result->getChild<GraphComponent>( i ); if( std::find( parameter->fields.begin(), parameter->fields.end(), child->getName().string() ) == parameter->fields.end() ) { result->removeChild( child ); } } } parent->setChild( name, result ); return result; }
void RenderManShader::loadShaderParameters( const IECore::Shader *shader, Gaffer::CompoundPlug *parametersPlug, bool keepExistingValues ) { const CompoundData *typeHints = shader->blindData()->member<CompoundData>( "ri:parameterTypeHints", true ); const StringVectorData *orderedParameterNamesData = shader->blindData()->member<StringVectorData>( "ri:orderedParameterNames", true ); const vector<string> &orderedParameterNames = orderedParameterNamesData->readable(); const StringVectorData *outputParameterNamesData = shader->blindData()->member<StringVectorData>( "ri:outputParameterNames", true ); const vector<string> &outputParameterNames = outputParameterNamesData->readable(); const CompoundData *annotations = shader->blindData()->member<CompoundData>( "ri:annotations", true ); // if we're not preserving existing values then remove all existing parameter plugs - the various // plug creators above know that if a plug exists then they should preserve its values. if( !keepExistingValues ) { for( int i = parametersPlug->children().size() - 1; i >= 0; --i ) { parametersPlug->removeChild( parametersPlug->getChild<GraphComponent>( i ) ); } } // make sure we have a plug to represent each parameter, reusing plugs wherever possible. set<string> validPlugNames; for( vector<string>::const_iterator it = orderedParameterNames.begin(), eIt = orderedParameterNames.end(); it != eIt; it++ ) { if( std::find( outputParameterNames.begin(), outputParameterNames.end(), *it ) != outputParameterNames.end() ) { continue; } // splines are represented by two parameters matched by a naming convention, and we map // those two parameters to a single SplinePlug. const bool endsWithValues = ends_with( *it, "Values" ); const bool endsWithPositions = ends_with( *it, "Positions" ); if( endsWithPositions || endsWithValues ) { string plugName( *it, 0, it->size() - ( endsWithValues ? 6 : 9 ) ); if( validPlugNames.find( plugName ) != validPlugNames.end() ) { continue; } // must use a smart pointers here because we may assign the data the parser creates (and which we therefore own) ConstFloatVectorDataPtr positions = shader->parametersData()->member<FloatVectorData>( plugName + "Positions" ); ConstDataPtr values = shader->parametersData()->member<Data>( plugName + "Values" ); if( positions && values ) { const StringData *defaultValuesAnnotation = annotations->member<StringData>( plugName + "Values.defaultValue" ); const StringData *defaultPositionsAnnotation = annotations->member<StringData>( plugName + "Positions.defaultValue" ); if( defaultValuesAnnotation ) { DataPtr parsedValues; if( values->isInstanceOf( Color3fVectorData::staticTypeId() ) ) { parsedValues = parseColors( defaultValuesAnnotation->readable() ); } else { parsedValues = parseFloats( defaultValuesAnnotation->readable() ); } if( parsedValues ) { values = parsedValues; } else { msg( Msg::Warning, "RenderManShader::loadShaderParameters", boost::format( "Unable to parse default value \"%s\" for parameter \"%s\"" ) % defaultValuesAnnotation->readable() % ( plugName + "Values" ) ); } } if( defaultPositionsAnnotation ) { FloatVectorDataPtr parsedPositions = parseFloats( defaultPositionsAnnotation->readable() ); if( parsedPositions ) { positions = parsedPositions; } else { msg( Msg::Warning, "RenderManShader::loadShaderParameters", boost::format( "Unable to parse default value \"%s\" for parameter \"%s\"" ) % defaultPositionsAnnotation->readable() % ( plugName + "Positions" ) ); } } switch( values->typeId() ) { case FloatVectorDataTypeId : loadSplineParameter<SplineffPlug>( parametersPlug, plugName, positions, values ); break; case Color3fVectorDataTypeId : loadSplineParameter<SplinefColor3fPlug>( parametersPlug, plugName, positions, values ); break; default : msg( Msg::Warning, "RenderManShader::loadShaderParameters", boost::format( "Spline \"%s\" has unsupported value type \"%s\"" ) % plugName % values->typeName() ); } validPlugNames.insert( plugName ); continue; } } // the other parameter types map more simply to a single plug each. const StringData *typeHint = typeHints->member<StringData>( *it, false ); const Data *defaultValue = shader->parametersData()->member<Data>( *it ); switch( defaultValue->typeId() ) { case StringDataTypeId : if( typeHint && typeHint->readable() == "shader" ) { loadCoshaderParameter( parametersPlug, *it ); } else { loadParameter<StringPlug>( parametersPlug, *it, static_cast<const StringData *>( defaultValue )->readable() ); } break; case FloatDataTypeId : loadNumericParameter( parametersPlug, *it, static_cast<const FloatData *>( defaultValue )->readable(), annotations ); break; case Color3fDataTypeId : loadCompoundNumericParameter<Color3fPlug>( parametersPlug, *it, static_cast<const Color3fData *>( defaultValue )->readable(), annotations ); break; case V3fDataTypeId : loadCompoundNumericParameter<V3fPlug>( parametersPlug, *it, static_cast<const V3fData *>( defaultValue )->readable(), annotations ); break; case StringVectorDataTypeId : if( typeHint && typeHint->readable() == "shader" ) { loadCoshaderArrayParameter( parametersPlug, *it, static_cast<const StringVectorData *>( defaultValue ) ); } else { loadArrayParameter<StringVectorDataPlug>( parametersPlug, *it, defaultValue, annotations ); } break; case FloatVectorDataTypeId : loadArrayParameter<FloatVectorDataPlug>( parametersPlug, *it, defaultValue, annotations ); break; case Color3fVectorDataTypeId : loadArrayParameter<Color3fVectorDataPlug>( parametersPlug, *it, defaultValue, annotations ); break; case V3fVectorDataTypeId : loadArrayParameter<V3fVectorDataPlug>( parametersPlug, *it, defaultValue, annotations ); break; default : msg( Msg::Warning, "RenderManShader::loadShaderParameters", boost::format( "Parameter \"%s\" has unsupported type \"%s\"" ) % *it % defaultValue->typeName() ); } validPlugNames.insert( *it ); } // remove any old plugs which it turned out we didn't need if( keepExistingValues ) { for( int i = parametersPlug->children().size() - 1; i >= 0; --i ) { GraphComponent *child = parametersPlug->getChild<GraphComponent>( i ); if( validPlugNames.find( child->getName().string() ) == validPlugNames.end() ) { parametersPlug->removeChild( child ); } } } }