Skip to content

Commit a2935e3

Browse files
authored
Merge pull request #1394 from johnhaddon/internedStringSubstitution
ShaderNetwork : Support InternedString attributes in substitutions
2 parents 89dcde0 + b4b8e2c commit a2935e3

File tree

7 files changed

+72
-34
lines changed

7 files changed

+72
-34
lines changed

Changes

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
10.5.x.x (relative to 10.5.3.0)
1+
10.5.x.x (relative to 10.5.4.0)
22
========
33

44

55

6+
10.5.4.0 (relative to 10.5.3.0)
7+
========
8+
9+
Improvements
10+
------------
11+
12+
- ShaderNetwork : Added support for InternedStringData attributes in string parameter substitutions.
13+
- MurmurHash : Added specialisation for `std::hash`, among other things allowing the use of MurmurHash as a key in `unordered_map`.
14+
- CompoundObject : Defaulted template argument to `Object` in `member()` methods.
15+
616
10.5.3.0 (relative to 10.5.2.1)
717
========
818

SConstruct

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ SConsignFile()
5656

5757
ieCoreMilestoneVersion = 10 # for announcing major milestones - may contain all of the below
5858
ieCoreMajorVersion = 5 # backwards-incompatible changes
59-
ieCoreMinorVersion = 3 # new backwards-compatible features
59+
ieCoreMinorVersion = 4 # new backwards-compatible features
6060
ieCorePatchVersion = 0 # bug fixes
6161
ieCoreVersionSuffix = "" # used for alpha/beta releases. Example: "a1", "b2", etc.
6262

@@ -1226,7 +1226,7 @@ else:
12261226
"/Fd${TARGET}.pdb",
12271227
],
12281228
)
1229-
1229+
12301230
# Reorder build commands so that `/external:I` includes come after `/I` includes.
12311231
# Otherwise we'll pick up the Gaffer includes from the build directory, and not
12321232
# the ones in the source tree.

include/IECore/CompoundObject.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,17 @@ class IECORE_API CompoundObject : public Object
6464
/// or doesn't match the type specified as the template argument, behavior
6565
/// is defined by the throwExceptions parameter. When this parameter is true a descriptive
6666
/// Exception is thrown, and when false 0 is returned.
67-
template<typename T>
67+
template<typename T = Object>
6868
T *member( const InternedString &name, bool throwExceptions = false );
69-
template<typename T>
69+
template<typename T = Object>
7070
const T *member( const InternedString &name, bool throwExceptions = false ) const;
7171

7272
/// A Convenience function to find an object in members().
7373
/// If the named object doesn't exist, if createIfMissing is true, an object will be added
7474
/// with the type's object factory create method. If false, or the named entry does not match the
7575
/// type specified as the template argument, behavior is defined by the throwExceptions parameter.
7676
/// When this parameter is true a descriptive Exception is thrown, and when false 0 is returned.
77-
template<typename T>
77+
template<typename T = Object>
7878
T *member( const InternedString &name, bool throwExceptions, bool createIfMissing );
7979

8080
/// Returns an instance of CompoundObject which can be shared by everyone - for instance a procedural

src/IECoreMaya/ParameterisedHolderModificationCmd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ void ParameterisedHolderModificationCmd::storeParametersWithNewValues( const IEC
323323
{
324324
childParameterPath = it->first;
325325
}
326-
storeParametersWithNewValues( it->second.get(), newCompound->member<Object>( it->first ), childParameterPath );
326+
storeParametersWithNewValues( it->second.get(), newCompound->member( it->first ), childParameterPath );
327327
}
328328

329329
const CompoundObject::ObjectMap &newChildren = static_cast<const CompoundObject *>( newValue )->members();

src/IECoreNuke/ParameterisedHolder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ int ParameterisedHolder<BaseType>::knob_changed( DD::Image::Knob *knob )
188188
ParameterisedInterface *parameterisedInterface = dynamic_cast<ParameterisedInterface *>( g_getParameterisedResult.get() );
189189
// apply current state
190190
ConstCompoundObjectPtr classSpecifier = runTimeCast<const CompoundObject>( m_classSpecifierKnob->getValue() );
191-
ConstObjectPtr handlerState = classSpecifier->member<Object>( "handlerState" );
191+
ConstObjectPtr handlerState = classSpecifier->member( "handlerState" );
192192
if( handlerState )
193193
{
194194
m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState.get() );
@@ -525,7 +525,7 @@ void ParameterisedHolder<BaseType>::updateParameterised( bool reload )
525525
// apply the previously stored handler state
526526

527527
ConstCompoundObjectPtr classSpecifier = runTimeCast<const CompoundObject>( m_classSpecifierKnob->getValue() );
528-
ConstObjectPtr handlerState = classSpecifier->member<Object>( "handlerState" );
528+
ConstObjectPtr handlerState = classSpecifier->member( "handlerState" );
529529
if( handlerState )
530530
{
531531
m_parameterHandler->setState( parameterisedInterface->parameters(), handlerState.get() );

src/IECoreScene/ShaderNetwork.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@ struct ReplaceFunctor
6666
std::string operator()( const boost::smatch & match )
6767
{
6868
// Search for attribute matching token
69-
const StringData *sourceAttribute = m_attributes->member<StringData>( match[1].str() );
70-
if( sourceAttribute )
69+
const Object *sourceAttribute = m_attributes->member( match[1].str() );
70+
if( auto stringData = runTimeCast<const StringData>( sourceAttribute ) )
7171
{
72-
return sourceAttribute->readable();
72+
return stringData->readable();
73+
}
74+
else if( auto internedStringData = runTimeCast<const InternedStringData>( sourceAttribute ) )
75+
{
76+
return internedStringData->readable().string();
7377
}
7478
else
7579
{
@@ -86,7 +90,7 @@ boost::regex attributeRegex()
8690
// Extract ATTR_NAME from the pattern <attr:ATTR_NAME>
8791
// Only match if the angle brackets haven't been escaped with a backslash
8892
static boost::regex r( "(?<!\\\\)<attr:([^>]*[^\\\\>])>" );
89-
return r;
93+
return r;
9094
}
9195

9296
bool stringFindSubstitutions( const std::string &target, std::unordered_set< InternedString > &requestedAttributes )
@@ -428,10 +432,14 @@ class ShaderNetwork::Implementation
428432
update();
429433
for( const auto &a : m_neededSubstitutions )
430434
{
431-
const StringData *sourceAttribute = attributes->member<StringData>( a );
432-
if( sourceAttribute )
435+
const Object *sourceAttribute = attributes->member( a );
436+
if( auto stringData = runTimeCast<const StringData>( sourceAttribute ) )
437+
{
438+
h.append( stringData->readable() );
439+
}
440+
else if( auto internedStringData = runTimeCast<const InternedStringData>( sourceAttribute ) )
433441
{
434-
h.append( sourceAttribute->readable() );
442+
h.append( internedStringData->readable().string() );
435443
}
436444
else
437445
{
@@ -737,7 +745,7 @@ class ShaderNetwork::Implementation
737745
}
738746
}
739747

740-
m_parmsNeedingSubstitution[ node.handle ] = parmsNeedingSub;
748+
m_parmsNeedingSubstitution[ node.handle ] = parmsNeedingSub;
741749
}
742750

743751
m_hash.append( m_output.shader );

test/IECoreScene/ShaderNetworkTest.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -513,23 +513,25 @@ def testUniqueHandles( self ) :
513513
{ "test" } | { "test{0}".format( x ) for x in range( 1, 20 ) }
514514
)
515515

516-
def testSubstitutions( self ):
517-
def runSubstitutionTest( shader, attributes ):
518-
n = IECoreScene.ShaderNetwork( shaders = { "s" : s } )
519-
a = IECore.CompoundObject( attributes )
520-
h = IECore.MurmurHash()
521-
n.hashSubstitutions( a, h )
522-
nSubst = n.copy()
523-
nSubst.applySubstitutions( a )
524-
return ( h, nSubst.getShader("s") )
516+
def __hashAndSubstitution( self, shader, attributes ) :
517+
518+
n = IECoreScene.ShaderNetwork( shaders = { "s" : shader } )
519+
a = IECore.CompoundObject( attributes )
520+
h = IECore.MurmurHash()
521+
n.hashSubstitutions( a, h )
522+
nSubst = n.copy()
523+
nSubst.applySubstitutions( a )
524+
return ( h, nSubst.getShader( "s" ) )
525+
526+
def testSubstitutions( self ) :
525527

526528
s = IECoreScene.Shader( "test", "surface",IECore.CompoundData( {
527529
"a" : IECore.StringData( "foo" ),
528530
"b" : IECore.FloatData( 42.42 ),
529531
"c" : IECore.StringVectorData( [ "foo", "bar" ] ),
530532
} ) )
531533

532-
( h, sSubst ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah" ) } )
534+
( h, sSubst ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah" ) } )
533535
self.assertEqual( h, IECore.MurmurHash() )
534536
self.assertEqual( s, sSubst )
535537

@@ -538,7 +540,7 @@ def runSubstitutionTest( shader, attributes ):
538540
"b" : IECore.FloatData( 42.42 ),
539541
"c" : IECore.StringVectorData( [ "<attr:bob>", "pre<attr:carol>", "<attr:fred>post", "<attr:bob><attr:carol> <attr:fred>" ] ),
540542
} ) )
541-
( h, sSubst ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah" ) } )
543+
( h, sSubst ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah" ) } )
542544
# Now that we've got substitutions, the hash should be non-default
543545
self.assertNotEqual( h, IECore.MurmurHash() )
544546

@@ -550,12 +552,12 @@ def runSubstitutionTest( shader, attributes ):
550552
self.assertEqual( sSubst.parameters["c"][2], "post" )
551553
self.assertEqual( sSubst.parameters["c"][3], " " )
552554

553-
( h2, sSubst2 ) = runSubstitutionTest( s, { "unused" : IECore.StringData( "blah2" ) } )
555+
( h2, sSubst2 ) = self.__hashAndSubstitution( s, { "unused" : IECore.StringData( "blah2" ) } )
554556
# The attribute being changed has no impact
555557
self.assertEqual( h, h2 )
556558
self.assertEqual( sSubst, sSubst2 )
557559

558-
( h3, sSubst3 ) = runSubstitutionTest( s, { "fred" : IECore.StringData( "CAT" ) } )
560+
( h3, sSubst3 ) = self.__hashAndSubstitution( s, { "fred" : IECore.StringData( "CAT" ) } )
559561
self.assertNotEqual( h, h3 )
560562
self.assertNotEqual( s, sSubst3 )
561563
self.assertEqual( sSubst3.parameters["a"].value, "preCATpost" )
@@ -564,7 +566,7 @@ def runSubstitutionTest( shader, attributes ):
564566
self.assertEqual( sSubst3.parameters["c"][2], "CATpost" )
565567
self.assertEqual( sSubst3.parameters["c"][3], " CAT" )
566568

567-
( h4, sSubst4 ) = runSubstitutionTest( s, { "fred" : IECore.StringData( "FISH" ) } )
569+
( h4, sSubst4 ) = self.__hashAndSubstitution( s, { "fred" : IECore.StringData( "FISH" ) } )
568570
self.assertNotEqual( h3, h4 )
569571
self.assertEqual( sSubst4.parameters["c"][2], "FISHpost" )
570572

@@ -573,7 +575,7 @@ def runSubstitutionTest( shader, attributes ):
573575
"bob" : IECore.StringData( "CAT" ),
574576
"carol" : IECore.StringData( "BIRD" )
575577
}
576-
( h5, sSubst5 ) = runSubstitutionTest( s, allAttributes )
578+
( h5, sSubst5 ) = self.__hashAndSubstitution( s, allAttributes )
577579
self.assertNotEqual( h4, h5 )
578580
self.assertEqual( sSubst5.parameters["a"].value, "preFISHpost" )
579581
self.assertEqual( sSubst5.parameters["c"][0], "CAT" )
@@ -587,14 +589,32 @@ def runSubstitutionTest( shader, attributes ):
587589
"b" : IECore.FloatData( 42.42 ),
588590
"c" : IECore.StringVectorData( [ r"\<attr:bob\>", r"\<attr:carol>", r"<attr:fred\>" ] ),
589591
} ) )
590-
( h6, sSubst6 ) = runSubstitutionTest( s, {} )
591-
( h7, sSubst7 ) = runSubstitutionTest( s, allAttributes )
592+
( h6, sSubst6 ) = self.__hashAndSubstitution( s, {} )
593+
( h7, sSubst7 ) = self.__hashAndSubstitution( s, allAttributes )
592594
self.assertEqual( h6, h7 )
593595
self.assertEqual( sSubst6, sSubst7 )
594596
self.assertEqual( sSubst6.parameters["a"].value, "pre<attr:fred>post" )
595597
self.assertEqual( sSubst6.parameters["c"][0], "<attr:bob>" )
596598
self.assertEqual( sSubst6.parameters["c"][1], "<attr:carol>" )
597599
self.assertEqual( sSubst6.parameters["c"][2], "<attr:fred>" )
598600

601+
def testInternedStringSubstitutions( self ) :
602+
603+
shader = IECoreScene.Shader(
604+
"test", "surface",
605+
IECore.CompoundData( {
606+
"a" : IECore.StringData( "<attr:internedString>" ),
607+
} )
608+
)
609+
610+
hash1, substitutedShader = self.__hashAndSubstitution( shader, { "internedString" : IECore.InternedStringData( "a" ) } )
611+
self.assertNotEqual( hash1, IECore.MurmurHash() )
612+
self.assertEqual( substitutedShader.parameters["a"], IECore.StringData( "a" ) )
613+
614+
hash2, substitutedShader = self.__hashAndSubstitution( shader, { "internedString" : IECore.InternedStringData( "b" ) } )
615+
self.assertNotEqual( hash2, IECore.MurmurHash() )
616+
self.assertNotEqual( hash2, hash1 )
617+
self.assertEqual( substitutedShader.parameters["a"], IECore.StringData( "b" ) )
618+
599619
if __name__ == "__main__":
600620
unittest.main()

0 commit comments

Comments
 (0)