5050#include " boost/regex.hpp"
5151
5252#include < array>
53+ #include < filesystem>
5354#include < unordered_map>
5455#include < unordered_set>
5556
@@ -811,8 +812,36 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811812 return std::make_pair ( 0 , 0 );
812813}
813814
815+ std::tuple< const std::string*, const std::string*, const std::string*, const std::string*, const std::string* >
816+ lookupSplinePlugSuffixes ( const std::string &shaderName )
817+ {
818+ // We seem to be able to identify shaders that should use the PRMan convention by whether they start
819+ // with one of the PRMan prefixes.
820+ // NOTE : This will fail if a shader is loaded from an explicit path, rather than being found in the
821+ // search path, because the shader name will include the full file path. We consider this an
822+ // acceptable failure, because shaders should be found in the search paths.
823+ if ( boost::starts_with ( shaderName, " Pxr" ) || boost::starts_with ( shaderName, " Lama" ) )
824+ {
825+ // The convention used by the PRMan shader library.
826+ static const std::string positions ( " _Knots" );
827+ static const std::string floatValues ( " _Floats" );
828+ static const std::string colorValues ( " _Colors" );
829+ static const std::string basis ( " _Interpolation" );
830+ static const std::string count ( " " );
831+ return { &positions, &floatValues, &colorValues, &basis, &count };
832+ }
833+ else
834+ {
835+ // The convention used by the OSL shaders that we ship with Gaffer.
836+ static const std::string positions ( " Positions" );
837+ static const std::string values ( " Values" );
838+ static const std::string basis ( " Basis" );
839+ return { &positions, &values, &values, &basis, nullptr };
840+ }
841+ }
842+
814843template <typename Spline>
815- void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
844+ void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string &shaderName )
816845{
817846 const char *basis = " catmull-rom" ;
818847 if ( spline.basis == Spline::Basis::bezier () )
@@ -866,9 +895,23 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
866895 }
867896 }
868897
869- newParameters[ name.string () + " Positions" ] = positionsData;
870- newParameters[ name.string () + " Values" ] = valuesData;
871- newParameters[ name.string () + " Basis" ] = new StringData ( basis );
898+ auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes ( shaderName );
899+
900+ newParameters[ name.string () + *positionsSuffix ] = positionsData;
901+ if constexpr ( std::is_same_v< typename Spline::YType, float > )
902+ {
903+ newParameters[ name.string () + *floatValuesSuffix ] = valuesData;
904+ }
905+ else
906+ {
907+ newParameters[ name.string () + *colorValuesSuffix ] = valuesData;
908+ }
909+ newParameters[ name.string () + *basisSuffix ] = new StringData ( basis );
910+
911+ if ( countSuffix )
912+ {
913+ newParameters[ name.string () + *countSuffix ] = new IntData ( positionsData->readable ().size () );
914+ }
872915}
873916
874917template <typename SplineData>
@@ -929,6 +972,122 @@ IECore::DataPtr loadSpline(
929972 return resultData;
930973}
931974
975+ void ensureParametersCopy (
976+ const IECore::CompoundDataMap ¶meters,
977+ IECore::CompoundDataPtr ¶metersDataCopy, CompoundDataMap *¶metersCopy
978+ )
979+ {
980+ if ( !parametersDataCopy )
981+ {
982+ parametersDataCopy = new CompoundData ();
983+ parametersCopy = ¶metersDataCopy->writable ();
984+ *parametersCopy = parameters;
985+ }
986+ }
987+
988+ IECore::ConstCompoundDataPtr collapseSplineParametersInternal ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string &shaderName )
989+ {
990+
991+ auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes ( shaderName );
992+
993+ const CompoundDataMap ¶meters ( parametersData->readable () );
994+ CompoundDataPtr newParametersData;
995+ CompoundDataMap *newParameters = nullptr ;
996+
997+ for ( const auto &maybeBasis : parameters )
998+ {
999+ if ( !boost::ends_with ( maybeBasis.first .string (), *basisSuffix ) )
1000+ {
1001+ continue ;
1002+ }
1003+ const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
1004+ if ( !basis )
1005+ {
1006+ continue ;
1007+ }
1008+
1009+
1010+ std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - basisSuffix->size () );
1011+ const IECore::InternedString positionsName = prefix + *positionsSuffix;
1012+ const FloatVectorData *floatPositions = parametersData->member <const FloatVectorData>( positionsName );
1013+ if ( !floatPositions )
1014+ {
1015+ continue ;
1016+ }
1017+
1018+ IECore::InternedString countName;
1019+ const IntData *countData = nullptr ;
1020+
1021+ if ( countSuffix )
1022+ {
1023+ countName = prefix + *countSuffix;
1024+ countData = parametersData->member <const IntData>( countName );
1025+
1026+ if ( !countData )
1027+ {
1028+ IECore::msg (
1029+ Msg::Error, " ShaderNetworkAlgo" ,
1030+ " Using spline format that expects count parameter, but no int count parameter found matching \" " + countName.string () + " \" "
1031+ );
1032+ }
1033+ else
1034+ {
1035+ if ( (int )floatPositions->readable ().size () != countData->readable () )
1036+ {
1037+ IECore::msg (
1038+ Msg::Error, " ShaderNetworkAlgo" ,
1039+ " Spline count \" " + countName.string () + " \" does not match length of data: " + std::to_string ( countData->readable () ) + " != " + std::to_string ( floatPositions->readable ().size () ) + " \" "
1040+ );
1041+ }
1042+ }
1043+ }
1044+
1045+ IECore::InternedString valuesName = prefix + *floatValuesSuffix;
1046+ IECore::DataPtr foundSpline;
1047+ if ( const FloatVectorData *floatValues = parametersData->member <const FloatVectorData>( valuesName ) )
1048+ {
1049+ foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1050+ }
1051+ else
1052+ {
1053+ valuesName = prefix + *colorValuesSuffix;
1054+ if ( const Color3fVectorData *color3Values = parametersData->member <const Color3fVectorData>( valuesName ) )
1055+ {
1056+ foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1057+ }
1058+ else if ( const Color4fVectorData *color4Values = parametersData->member <const Color4fVectorData>( valuesName ) )
1059+ {
1060+ foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1061+ }
1062+
1063+ }
1064+
1065+ if ( foundSpline )
1066+ {
1067+ ensureParametersCopy ( parameters, newParametersData, newParameters );
1068+ newParameters->erase ( maybeBasis.first );
1069+ newParameters->erase ( positionsName );
1070+ newParameters->erase ( valuesName );
1071+ if ( countData )
1072+ {
1073+ newParameters->erase ( countName );
1074+ }
1075+
1076+ (*newParameters)[prefix] = foundSpline;
1077+
1078+ }
1079+ }
1080+
1081+ if ( newParametersData )
1082+ {
1083+ return newParametersData;
1084+ }
1085+ else
1086+ {
1087+ return parametersData;
1088+ }
1089+ }
1090+
9321091const std::string g_oslShader ( " osl:shader" );
9331092
9341093const std::string g_colorToArrayAdapter ( " Utility/__ColorToArray" );
@@ -1003,19 +1162,6 @@ std::pair< InternedString, int > createSplineInputAdapter(
10031162 return std::make_pair ( adapterHandle, getEndPointDuplication ( splineData->readable ().basis ).first );
10041163}
10051164
1006- void ensureParametersCopy (
1007- const IECore::CompoundDataMap ¶meters,
1008- IECore::CompoundDataPtr ¶metersDataCopy, CompoundDataMap *¶metersCopy
1009- )
1010- {
1011- if ( !parametersDataCopy )
1012- {
1013- parametersDataCopy = new CompoundData ();
1014- parametersCopy = ¶metersDataCopy->writable ();
1015- *parametersCopy = parameters;
1016- }
1017- }
1018-
10191165} // namespace
10201166
10211167void ShaderNetworkAlgo::collapseSplines ( ShaderNetwork *network, std::string targetPrefix )
@@ -1040,12 +1186,12 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10401186 }
10411187
10421188 // For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1043- ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData () );
1189+ ConstCompoundDataPtr collapsed = collapseSplineParametersInternal ( shader->parametersData (), shader-> getName () );
10441190 if ( collapsed != shader->parametersData () )
10451191 {
1046- // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
1192+ // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameterInternals
10471193 // doesn't match the input, it is freshly allocated. Once collapseSplineParameters is fully
1048- // deprecated, and no longer visible publicly, an internal version of collapseSplineParameters could
1194+ // deprecated, and no longer visible publicly, collapseSplineParametersInternal could
10491195 // just return a non-const new parameter data, or nullptr if no changes are needed.
10501196 network->setShader ( name, std::move ( new Shader ( shader->getName (), shader->getType (), const_cast < CompoundData *>( collapsed.get () ) ) ) );
10511197 }
@@ -1167,13 +1313,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11671313 {
11681314 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11691315 newParameters->erase ( name );
1170- expandSpline ( name, colorSpline->readable (), *newParameters );
1316+ expandSpline ( name, colorSpline->readable (), *newParameters, s. second -> getName () );
11711317 }
11721318 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get () ) )
11731319 {
11741320 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11751321 newParameters->erase ( name );
1176- expandSpline ( name, floatSpline->readable (), *newParameters );
1322+ expandSpline ( name, floatSpline->readable (), *newParameters, s. second -> getName () );
11771323 }
11781324 }
11791325
@@ -1291,76 +1437,7 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12911437
12921438IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
12931439{
1294- const CompoundDataMap ¶meters ( parametersData->readable () );
1295- CompoundDataPtr newParametersData;
1296- CompoundDataMap *newParameters = nullptr ;
1297-
1298- for ( const auto &maybeBasis : parameters )
1299- {
1300- if ( !boost::ends_with ( maybeBasis.first .string (), " Basis" ) )
1301- {
1302- continue ;
1303- }
1304- const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
1305- if ( !basis )
1306- {
1307- continue ;
1308- }
1309-
1310-
1311- std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - 5 );
1312- IECore::InternedString positionsName = prefix + " Positions" ;
1313- const auto positionsIter = parameters.find ( positionsName );
1314- const FloatVectorData *floatPositions = nullptr ;
1315-
1316- if ( positionsIter != parameters.end () )
1317- {
1318- floatPositions = runTimeCast<const FloatVectorData>( positionsIter->second .get () );
1319- }
1320-
1321- if ( !floatPositions )
1322- {
1323- continue ;
1324- }
1325-
1326- IECore::InternedString valuesName = prefix + " Values" ;
1327- const auto valuesIter = parameters.find ( valuesName );
1328-
1329- IECore::DataPtr foundSpline;
1330- if ( valuesIter != parameters.end () )
1331- {
1332- if ( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second .get () ) )
1333- {
1334- foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1335- }
1336- else if ( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second .get () ) )
1337- {
1338- foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1339- }
1340- else if ( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second .get () ) )
1341- {
1342- foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1343- }
1344- }
1345-
1346- if ( foundSpline )
1347- {
1348- ensureParametersCopy ( parameters, newParametersData, newParameters );
1349- (*newParameters)[prefix] = foundSpline;
1350- newParameters->erase ( maybeBasis.first );
1351- newParameters->erase ( positionsName );
1352- newParameters->erase ( valuesName );
1353- }
1354- }
1355-
1356- if ( newParametersData )
1357- {
1358- return newParametersData;
1359- }
1360- else
1361- {
1362- return parametersData;
1363- }
1440+ return collapseSplineParametersInternal ( parametersData, " " );
13641441}
13651442
13661443IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
@@ -1376,13 +1453,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13761453 {
13771454 ensureParametersCopy ( parameters, newParametersData, newParameters );
13781455 newParameters->erase ( i.first );
1379- expandSpline ( i.first , colorSpline->readable (), *newParameters );
1456+ expandSpline ( i.first , colorSpline->readable (), *newParameters, " " );
13801457 }
13811458 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second .get () ) )
13821459 {
13831460 ensureParametersCopy ( parameters, newParametersData, newParameters );
13841461 newParameters->erase ( i.first );
1385- expandSpline ( i.first , floatSpline->readable (), *newParameters );
1462+ expandSpline ( i.first , floatSpline->readable (), *newParameters, " " );
13861463 }
13871464 }
13881465
0 commit comments