5050#include " boost/regex.hpp"
5151
5252#include < array>
53+ #include < filesystem>
5354#include < unordered_map>
5455#include < unordered_set>
5556
@@ -811,8 +812,31 @@ 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 &shaderBaseName )
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+ if ( boost::starts_with ( shaderBaseName, " Pxr" ) || boost::starts_with ( shaderBaseName, " Lama" ) )
821+ {
822+ static const std::string positions ( " _Knots" );
823+ static const std::string floatValues ( " _Floats" );
824+ static const std::string colorValues ( " _Colors" );
825+ static const std::string basis ( " _Interpolation" );
826+ static const std::string count ( " " );
827+ return { &positions, &floatValues, &colorValues, &basis, &count };
828+ }
829+ else
830+ {
831+ static const std::string positions ( " Positions" );
832+ static const std::string values ( " Values" );
833+ static const std::string basis ( " Basis" );
834+ return { &positions, &values, &values, &basis, nullptr };
835+ }
836+ }
837+
814838template <typename Spline>
815- void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
839+ void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string &shaderBaseName )
816840{
817841 const char *basis = " catmull-rom" ;
818842 if ( spline.basis == Spline::Basis::bezier () )
@@ -866,9 +890,23 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
866890 }
867891 }
868892
869- newParameters[ name.string () + " Positions" ] = positionsData;
870- newParameters[ name.string () + " Values" ] = valuesData;
871- newParameters[ name.string () + " Basis" ] = new StringData ( basis );
893+ auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes ( shaderBaseName );
894+
895+ newParameters[ name.string () + *positionsSuffix ] = positionsData;
896+ if constexpr ( std::is_same_v< typename Spline::YType, float > )
897+ {
898+ newParameters[ name.string () + *floatValuesSuffix ] = valuesData;
899+ }
900+ else
901+ {
902+ newParameters[ name.string () + *colorValuesSuffix ] = valuesData;
903+ }
904+ newParameters[ name.string () + *basisSuffix ] = new StringData ( basis );
905+
906+ if ( countSuffix )
907+ {
908+ newParameters[ name.string () + *countSuffix ] = new IntData ( positionsData->readable ().size () );
909+ }
872910}
873911
874912template <typename SplineData>
@@ -929,6 +967,131 @@ IECore::DataPtr loadSpline(
929967 return resultData;
930968}
931969
970+ void ensureParametersCopy (
971+ const IECore::CompoundDataMap ¶meters,
972+ IECore::CompoundDataPtr ¶metersDataCopy, CompoundDataMap *¶metersCopy
973+ )
974+ {
975+ if ( !parametersDataCopy )
976+ {
977+ parametersDataCopy = new CompoundData ();
978+ parametersCopy = ¶metersDataCopy->writable ();
979+ *parametersCopy = parameters;
980+ }
981+ }
982+
983+ IECore::ConstCompoundDataPtr collapseSplineParametersInternal ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string &shaderBaseName )
984+ {
985+
986+ auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes ( shaderBaseName );
987+
988+ const CompoundDataMap ¶meters ( parametersData->readable () );
989+ CompoundDataPtr newParametersData;
990+ CompoundDataMap *newParameters = nullptr ;
991+
992+ for ( const auto &maybeBasis : parameters )
993+ {
994+ if ( !boost::ends_with ( maybeBasis.first .string (), *basisSuffix ) )
995+ {
996+ continue ;
997+ }
998+ const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
999+ if ( !basis )
1000+ {
1001+ continue ;
1002+ }
1003+
1004+
1005+ std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - basisSuffix->size () );
1006+ IECore::InternedString positionsName = prefix + *positionsSuffix;
1007+ const auto positionsIter = parameters.find ( positionsName );
1008+ const FloatVectorData *floatPositions = nullptr ;
1009+
1010+ if ( positionsIter != parameters.end () )
1011+ {
1012+ floatPositions = runTimeCast<const FloatVectorData>( positionsIter->second .get () );
1013+ }
1014+
1015+ if ( !floatPositions )
1016+ {
1017+ continue ;
1018+ }
1019+
1020+ if ( countSuffix )
1021+ {
1022+ IECore::InternedString countName = prefix + *countSuffix;
1023+ const auto countIter = parameters.find ( countName );
1024+ const IntData *countData = nullptr ;
1025+ if ( countIter == parameters.end () )
1026+ {
1027+ countData = runTimeCast<const IntData>( countIter->second .get () );
1028+ }
1029+
1030+ if ( !countData )
1031+ {
1032+ IECore::msg (
1033+ Msg::Error, " ShaderNetworkAlgo" ,
1034+ " Using spline format that expects count plug, but no int count plug found matching \" " + countName.string () + " \" "
1035+ );
1036+ }
1037+ else
1038+ {
1039+ if ( (int )floatPositions->readable ().size () != countData->readable () )
1040+ {
1041+ IECore::msg (
1042+ Msg::Error, " ShaderNetworkAlgo" ,
1043+ " Spline count \" " + countName.string () + " \" does not match length of data: " + std::to_string ( countData->readable () ) + " != " + std::to_string ( floatPositions->readable ().size () ) + " \" "
1044+ );
1045+ }
1046+ }
1047+ }
1048+
1049+ IECore::InternedString floatValuesName = prefix + *floatValuesSuffix;
1050+ auto valuesIter = parameters.find ( floatValuesName );
1051+ if ( valuesIter == parameters.end () )
1052+ {
1053+ IECore::InternedString colorValuesName = prefix + *colorValuesSuffix;
1054+ valuesIter = parameters.find ( colorValuesName );
1055+ }
1056+
1057+
1058+ IECore::DataPtr foundSpline;
1059+ if ( valuesIter != parameters.end () )
1060+ {
1061+ if ( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second .get () ) )
1062+ {
1063+ foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1064+ }
1065+ else if ( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second .get () ) )
1066+ {
1067+ foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1068+ }
1069+ else if ( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second .get () ) )
1070+ {
1071+ foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1072+ }
1073+ }
1074+
1075+ if ( foundSpline )
1076+ {
1077+ ensureParametersCopy ( parameters, newParametersData, newParameters );
1078+ (*newParameters)[prefix] = foundSpline;
1079+ newParameters->erase ( maybeBasis.first );
1080+ newParameters->erase ( positionsName );
1081+ newParameters->erase ( valuesIter->first );
1082+ }
1083+ }
1084+
1085+ if ( newParametersData )
1086+ {
1087+ return newParametersData;
1088+ }
1089+ else
1090+ {
1091+ return parametersData;
1092+ }
1093+ }
1094+
9321095const std::string g_oslShader ( " osl:shader" );
9331096
9341097const std::string g_colorToArrayAdapter ( " Utility/__ColorToArray" );
@@ -1003,17 +1166,9 @@ std::pair< InternedString, int > createSplineInputAdapter(
10031166 return std::make_pair ( adapterHandle, getEndPointDuplication ( splineData->readable ().basis ).first );
10041167}
10051168
1006- void ensureParametersCopy (
1007- const IECore::CompoundDataMap ¶meters,
1008- IECore::CompoundDataPtr ¶metersDataCopy, CompoundDataMap *¶metersCopy
1009- )
1169+ std::string shaderBaseNameFromPath ( const std::string shaderName )
10101170{
1011- if ( !parametersDataCopy )
1012- {
1013- parametersDataCopy = new CompoundData ();
1014- parametersCopy = ¶metersDataCopy->writable ();
1015- *parametersCopy = parameters;
1016- }
1171+ return std::filesystem::path ( shaderName ).filename ().string ();
10171172}
10181173
10191174} // namespace
@@ -1040,12 +1195,12 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10401195 }
10411196
10421197 // For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1043- ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData () );
1198+ ConstCompoundDataPtr collapsed = collapseSplineParametersInternal ( shader->parametersData (), shaderBaseNameFromPath ( shader-> getName () ) );
10441199 if ( collapsed != shader->parametersData () )
10451200 {
1046- // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
1201+ // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameterInternals
10471202 // 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
1203+ // deprecated, and no longer visible publicly, an internal version of collapseSplineParametersInternal could
10491204 // just return a non-const new parameter data, or nullptr if no changes are needed.
10501205 network->setShader ( name, std::move ( new Shader ( shader->getName (), shader->getType (), const_cast < CompoundData *>( collapsed.get () ) ) ) );
10511206 }
@@ -1167,13 +1322,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11671322 {
11681323 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11691324 newParameters->erase ( name );
1170- expandSpline ( name, colorSpline->readable (), *newParameters );
1325+ expandSpline ( name, colorSpline->readable (), *newParameters, shaderBaseNameFromPath ( s. second -> getName () ) );
11711326 }
11721327 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get () ) )
11731328 {
11741329 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11751330 newParameters->erase ( name );
1176- expandSpline ( name, floatSpline->readable (), *newParameters );
1331+ expandSpline ( name, floatSpline->readable (), *newParameters, shaderBaseNameFromPath ( s. second -> getName () ) );
11771332 }
11781333 }
11791334
@@ -1291,76 +1446,7 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12911446
12921447IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
12931448{
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- }
1449+ return collapseSplineParametersInternal ( parametersData, " " );
13641450}
13651451
13661452IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
@@ -1376,13 +1462,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13761462 {
13771463 ensureParametersCopy ( parameters, newParametersData, newParameters );
13781464 newParameters->erase ( i.first );
1379- expandSpline ( i.first , colorSpline->readable (), *newParameters );
1465+ expandSpline ( i.first , colorSpline->readable (), *newParameters, " " );
13801466 }
13811467 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second .get () ) )
13821468 {
13831469 ensureParametersCopy ( parameters, newParametersData, newParameters );
13841470 newParameters->erase ( i.first );
1385- expandSpline ( i.first , floatSpline->readable (), *newParameters );
1471+ expandSpline ( i.first , floatSpline->readable (), *newParameters, " " );
13861472 }
13871473 }
13881474
0 commit comments