From edc2b63154f08cdfa0320507063843836b0ee428 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 9 Nov 2023 09:20:51 +0000 Subject: [PATCH 1/5] Update Changes --- Changes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changes b/Changes index 0da2a88fe5..93ed55b7cb 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,10 @@ 10.5.x.x (relative to 10.5.3.0) ======== +Improvements +------------ +- MurmurHash : Added specialisation for `std::hash`, among other things allowing the use of MurmurHash as a key in `unordered_map`. 10.5.3.0 (relative to 10.5.2.1) ======== From 2237feea731840b9d8fbf15ebad1aee185c46160 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 9 Nov 2023 09:25:03 +0000 Subject: [PATCH 2/5] CompoundObject : Default `member()` template argument to `Object` --- Changes | 1 + include/IECore/CompoundObject.h | 6 +++--- src/IECoreMaya/ParameterisedHolderModificationCmd.cpp | 2 +- src/IECoreNuke/ParameterisedHolder.cpp | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 93ed55b7cb..68461fd203 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,7 @@ Improvements ------------ - MurmurHash : Added specialisation for `std::hash`, among other things allowing the use of MurmurHash as a key in `unordered_map`. +- CompoundObject : Defaulted template argument to `Object` in `member()` methods. 10.5.3.0 (relative to 10.5.2.1) ======== diff --git a/include/IECore/CompoundObject.h b/include/IECore/CompoundObject.h index ce92c68246..2f5ef137ed 100644 --- a/include/IECore/CompoundObject.h +++ b/include/IECore/CompoundObject.h @@ -64,9 +64,9 @@ class IECORE_API CompoundObject : public Object /// or doesn't match the type specified as the template argument, behavior /// is defined by the throwExceptions parameter. When this parameter is true a descriptive /// Exception is thrown, and when false 0 is returned. - template + template T *member( const InternedString &name, bool throwExceptions = false ); - template + template const T *member( const InternedString &name, bool throwExceptions = false ) const; /// A Convenience function to find an object in members(). @@ -74,7 +74,7 @@ class IECORE_API CompoundObject : public Object /// with the type's object factory create method. If false, or the named entry does not match the /// type specified as the template argument, behavior is defined by the throwExceptions parameter. /// When this parameter is true a descriptive Exception is thrown, and when false 0 is returned. - template + template T *member( const InternedString &name, bool throwExceptions, bool createIfMissing ); /// Returns an instance of CompoundObject which can be shared by everyone - for instance a procedural diff --git a/src/IECoreMaya/ParameterisedHolderModificationCmd.cpp b/src/IECoreMaya/ParameterisedHolderModificationCmd.cpp index ee834fb079..df839e1cdb 100644 --- a/src/IECoreMaya/ParameterisedHolderModificationCmd.cpp +++ b/src/IECoreMaya/ParameterisedHolderModificationCmd.cpp @@ -323,7 +323,7 @@ void ParameterisedHolderModificationCmd::storeParametersWithNewValues( const IEC { childParameterPath = it->first; } - storeParametersWithNewValues( it->second.get(), newCompound->member( it->first ), childParameterPath ); + storeParametersWithNewValues( it->second.get(), newCompound->member( it->first ), childParameterPath ); } const CompoundObject::ObjectMap &newChildren = static_cast( newValue )->members(); diff --git a/src/IECoreNuke/ParameterisedHolder.cpp b/src/IECoreNuke/ParameterisedHolder.cpp index ce4373fa7f..1321b9798d 100644 --- a/src/IECoreNuke/ParameterisedHolder.cpp +++ b/src/IECoreNuke/ParameterisedHolder.cpp @@ -188,7 +188,7 @@ int ParameterisedHolder::knob_changed( DD::Image::Knob *knob ) ParameterisedInterface *parameterisedInterface = dynamic_cast( g_getParameterisedResult.get() ); // apply current state ConstCompoundObjectPtr classSpecifier = runTimeCast( m_classSpecifierKnob->getValue() ); - ConstObjectPtr handlerState = classSpecifier->member( "handlerState" ); + ConstObjectPtr handlerState = classSpecifier->member( "handlerState" ); if( handlerState ) { m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState.get() ); @@ -525,7 +525,7 @@ void ParameterisedHolder::updateParameterised( bool reload ) // apply the previously stored handler state ConstCompoundObjectPtr classSpecifier = runTimeCast( m_classSpecifierKnob->getValue() ); - ConstObjectPtr handlerState = classSpecifier->member( "handlerState" ); + ConstObjectPtr handlerState = classSpecifier->member( "handlerState" ); if( handlerState ) { m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState.get() ); From 16d9ee77622c5d45a7a87e282db12d4c9f17c2e6 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 9 Nov 2023 09:26:03 +0000 Subject: [PATCH 3/5] ShaderNetwork, SConstruct : Remove trailing whitespace --- SConstruct | 2 +- src/IECoreScene/ShaderNetwork.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SConstruct b/SConstruct index d60055020c..f6fb4ffd40 100644 --- a/SConstruct +++ b/SConstruct @@ -1226,7 +1226,7 @@ else: "/Fd${TARGET}.pdb", ], ) - + # Reorder build commands so that `/external:I` includes come after `/I` includes. # Otherwise we'll pick up the Gaffer includes from the build directory, and not # the ones in the source tree. diff --git a/src/IECoreScene/ShaderNetwork.cpp b/src/IECoreScene/ShaderNetwork.cpp index 0cd18d898a..0d349f1c6d 100644 --- a/src/IECoreScene/ShaderNetwork.cpp +++ b/src/IECoreScene/ShaderNetwork.cpp @@ -86,7 +86,7 @@ boost::regex attributeRegex() // Extract ATTR_NAME from the pattern // Only match if the angle brackets haven't been escaped with a backslash static boost::regex r( "(?]*[^\\\\>])>" ); - return r; + return r; } bool stringFindSubstitutions( const std::string &target, std::unordered_set< InternedString > &requestedAttributes ) @@ -737,7 +737,7 @@ class ShaderNetwork::Implementation } } - m_parmsNeedingSubstitution[ node.handle ] = parmsNeedingSub; + m_parmsNeedingSubstitution[ node.handle ] = parmsNeedingSub; } m_hash.append( m_output.shader ); From 7a3e441fb30aec512f034a7ad0f620317898812f Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 9 Nov 2023 09:33:01 +0000 Subject: [PATCH 4/5] ShaderNetwork : Support InternedString attributes in substitutions This is needed to allow USD `token` attributes to be referenced by a substitution. --- Changes | 1 + src/IECoreScene/ShaderNetwork.cpp | 20 +++++++--- test/IECoreScene/ShaderNetworkTest.py | 54 ++++++++++++++++++--------- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/Changes b/Changes index 68461fd203..dd117e9039 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,7 @@ Improvements ------------ +- ShaderNetwork : Added support for InternedStringData attributes in string parameter substitutions. - MurmurHash : Added specialisation for `std::hash`, among other things allowing the use of MurmurHash as a key in `unordered_map`. - CompoundObject : Defaulted template argument to `Object` in `member()` methods. diff --git a/src/IECoreScene/ShaderNetwork.cpp b/src/IECoreScene/ShaderNetwork.cpp index 0d349f1c6d..eb98abc39f 100644 --- a/src/IECoreScene/ShaderNetwork.cpp +++ b/src/IECoreScene/ShaderNetwork.cpp @@ -66,10 +66,14 @@ struct ReplaceFunctor std::string operator()( const boost::smatch & match ) { // Search for attribute matching token - const StringData *sourceAttribute = m_attributes->member( match[1].str() ); - if( sourceAttribute ) + const Object *sourceAttribute = m_attributes->member( match[1].str() ); + if( auto stringData = runTimeCast( sourceAttribute ) ) { - return sourceAttribute->readable(); + return stringData->readable(); + } + else if( auto internedStringData = runTimeCast( sourceAttribute ) ) + { + return internedStringData->readable().string(); } else { @@ -428,10 +432,14 @@ class ShaderNetwork::Implementation update(); for( const auto &a : m_neededSubstitutions ) { - const StringData *sourceAttribute = attributes->member( a ); - if( sourceAttribute ) + const Object *sourceAttribute = attributes->member( a ); + if( auto stringData = runTimeCast( sourceAttribute ) ) + { + h.append( stringData->readable() ); + } + else if( auto internedStringData = runTimeCast( sourceAttribute ) ) { - h.append( sourceAttribute->readable() ); + h.append( internedStringData->readable().string() ); } else { diff --git a/test/IECoreScene/ShaderNetworkTest.py b/test/IECoreScene/ShaderNetworkTest.py index c255bd1403..1f7f5373e6 100644 --- a/test/IECoreScene/ShaderNetworkTest.py +++ b/test/IECoreScene/ShaderNetworkTest.py @@ -513,15 +513,17 @@ def testUniqueHandles( self ) : { "test" } | { "test{0}".format( x ) for x in range( 1, 20 ) } ) - def testSubstitutions( self ): - def runSubstitutionTest( shader, attributes ): - n = IECoreScene.ShaderNetwork( shaders = { "s" : s } ) - a = IECore.CompoundObject( attributes ) - h = IECore.MurmurHash() - n.hashSubstitutions( a, h ) - nSubst = n.copy() - nSubst.applySubstitutions( a ) - return ( h, nSubst.getShader("s") ) + def __hashAndSubstitution( self, shader, attributes ) : + + n = IECoreScene.ShaderNetwork( shaders = { "s" : shader } ) + a = IECore.CompoundObject( attributes ) + h = IECore.MurmurHash() + n.hashSubstitutions( a, h ) + nSubst = n.copy() + nSubst.applySubstitutions( a ) + return ( h, nSubst.getShader( "s" ) ) + + def testSubstitutions( self ) : s = IECoreScene.Shader( "test", "surface",IECore.CompoundData( { "a" : IECore.StringData( "foo" ), @@ -529,7 +531,7 @@ def runSubstitutionTest( shader, attributes ): "c" : IECore.StringVectorData( [ "foo", "bar" ] ), } ) ) - ( h, sSubst ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah" ) } ) + ( h, sSubst ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah" ) } ) self.assertEqual( h, IECore.MurmurHash() ) self.assertEqual( s, sSubst ) @@ -538,7 +540,7 @@ def runSubstitutionTest( shader, attributes ): "b" : IECore.FloatData( 42.42 ), "c" : IECore.StringVectorData( [ "", "pre", "post", " " ] ), } ) ) - ( h, sSubst ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah" ) } ) + ( h, sSubst ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah" ) } ) # Now that we've got substitutions, the hash should be non-default self.assertNotEqual( h, IECore.MurmurHash() ) @@ -550,12 +552,12 @@ def runSubstitutionTest( shader, attributes ): self.assertEqual( sSubst.parameters["c"][2], "post" ) self.assertEqual( sSubst.parameters["c"][3], " " ) - ( h2, sSubst2 ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah2" ) } ) + ( h2, sSubst2 ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah2" ) } ) # The attribute being changed has no impact self.assertEqual( h, h2 ) self.assertEqual( sSubst, sSubst2 ) - ( h3, sSubst3 ) = runSubstitutionTest( s, { "fred" : IECore.StringData( "CAT" ) } ) + ( h3, sSubst3 ) = self.__hashAndSubstitution( s, { "fred" : IECore.StringData( "CAT" ) } ) self.assertNotEqual( h, h3 ) self.assertNotEqual( s, sSubst3 ) self.assertEqual( sSubst3.parameters["a"].value, "preCATpost" ) @@ -564,7 +566,7 @@ def runSubstitutionTest( shader, attributes ): self.assertEqual( sSubst3.parameters["c"][2], "CATpost" ) self.assertEqual( sSubst3.parameters["c"][3], " CAT" ) - ( h4, sSubst4 ) = runSubstitutionTest( s, { "fred" : IECore.StringData( "FISH" ) } ) + ( h4, sSubst4 ) = self.__hashAndSubstitution( s, { "fred" : IECore.StringData( "FISH" ) } ) self.assertNotEqual( h3, h4 ) self.assertEqual( sSubst4.parameters["c"][2], "FISHpost" ) @@ -573,7 +575,7 @@ def runSubstitutionTest( shader, attributes ): "bob" : IECore.StringData( "CAT" ), "carol" : IECore.StringData( "BIRD" ) } - ( h5, sSubst5 ) = runSubstitutionTest( s, allAttributes ) + ( h5, sSubst5 ) = self.__hashAndSubstitution( s, allAttributes ) self.assertNotEqual( h4, h5 ) self.assertEqual( sSubst5.parameters["a"].value, "preFISHpost" ) self.assertEqual( sSubst5.parameters["c"][0], "CAT" ) @@ -587,8 +589,8 @@ def runSubstitutionTest( shader, attributes ): "b" : IECore.FloatData( 42.42 ), "c" : IECore.StringVectorData( [ r"\", r"\", r"" ] ), } ) ) - ( h6, sSubst6 ) = runSubstitutionTest( s, {} ) - ( h7, sSubst7 ) = runSubstitutionTest( s, allAttributes ) + ( h6, sSubst6 ) = self.__hashAndSubstitution( s, {} ) + ( h7, sSubst7 ) = self.__hashAndSubstitution( s, allAttributes ) self.assertEqual( h6, h7 ) self.assertEqual( sSubst6, sSubst7 ) self.assertEqual( sSubst6.parameters["a"].value, "prepost" ) @@ -596,5 +598,23 @@ def runSubstitutionTest( shader, attributes ): self.assertEqual( sSubst6.parameters["c"][1], "" ) self.assertEqual( sSubst6.parameters["c"][2], "" ) + def testInternedStringSubstitutions( self ) : + + shader = IECoreScene.Shader( + "test", "surface", + IECore.CompoundData( { + "a" : IECore.StringData( "" ), + } ) + ) + + hash1, substitutedShader = self.__hashAndSubstitution( shader, { "internedString" : IECore.InternedStringData( "a" ) } ) + self.assertNotEqual( hash1, IECore.MurmurHash() ) + self.assertEqual( substitutedShader.parameters["a"], IECore.StringData( "a" ) ) + + hash2, substitutedShader = self.__hashAndSubstitution( shader, { "internedString" : IECore.InternedStringData( "b" ) } ) + self.assertNotEqual( hash2, IECore.MurmurHash() ) + self.assertNotEqual( hash2, hash1 ) + self.assertEqual( substitutedShader.parameters["a"], IECore.StringData( "b" ) ) + if __name__ == "__main__": unittest.main() From b4b8e2c0f96a44e319154754b2c7f5196901dd95 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 9 Nov 2023 09:35:29 +0000 Subject: [PATCH 5/5] Bump version to 10.5.4.0 --- Changes | 7 ++++++- SConstruct | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index dd117e9039..2007db8c94 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,9 @@ -10.5.x.x (relative to 10.5.3.0) +10.5.x.x (relative to 10.5.4.0) +======== + + + +10.5.4.0 (relative to 10.5.3.0) ======== Improvements diff --git a/SConstruct b/SConstruct index f6fb4ffd40..e71936c911 100644 --- a/SConstruct +++ b/SConstruct @@ -56,7 +56,7 @@ SConsignFile() ieCoreMilestoneVersion = 10 # for announcing major milestones - may contain all of the below ieCoreMajorVersion = 5 # backwards-incompatible changes -ieCoreMinorVersion = 3 # new backwards-compatible features +ieCoreMinorVersion = 4 # new backwards-compatible features ieCorePatchVersion = 0 # bug fixes ieCoreVersionSuffix = "" # used for alpha/beta releases. Example: "a1", "b2", etc.