Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenColorIO : Defer expansion of context variables in OCIO vars #5898

Merged
merged 1 commit into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Improvements
- Added support for dropping an Edit Scope node onto the widget to set it as the current Edit Scope.
- Added support for middle-dragging from the widget to access the current Edit Scope node.
- ArnoldAttributes : Added syntax highlighting and auto-complete for set expressions on the `shadowGroup` plug.
- OpenColorIO : When a script-level OpenColorIO variable contains a Gaffer `${contextVariable}` reference, its evaluation is now deferred to the point of use. This allows it to pick up overrides introduced by nodes such as ContextVariables and Wedge.

Fixes
-----

- Viewer : Fixed handling of Gaffer `${contextVariable}` references in OpenColorIO variable values. The Viewer now updates the Display Transform appropriately when the value of the context variable changes.

API
---
Expand Down
2 changes: 1 addition & 1 deletion python/GafferImageTest/ColorSpaceTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def testConfigFromGafferContext( self ) :

with Gaffer.Context() as c :

GafferImage.OpenColorIOAlgo.setConfig( c, str( self.openColorIOPath() / "context.ocio" ) )
GafferImage.OpenColorIOAlgo.setConfig( c, ( self.openColorIOPath() / "context.ocio" ).as_posix() )
GafferImage.OpenColorIOAlgo.addVariable( c, "LUT", "srgb.spi1d" )
GafferImage.OpenColorIOAlgo.addVariable( c, "CDL", "cineon.spi1d" )

Expand Down
2 changes: 1 addition & 1 deletion python/GafferImageTest/DisplayTransformTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def testDisplayAndViewDefaultToConfig( self ) :
explicitDisplayTransform["view"].setValue( config.getDefaultView( config.getDefaultDisplay() ) )

with Gaffer.Context() as context :
GafferImage.OpenColorIOAlgo.setConfig( context, str( configPath ) )
GafferImage.OpenColorIOAlgo.setConfig( context, configPath.as_posix() )
self.assertImagesEqual( defaultDisplayTransform["out"], explicitDisplayTransform["out"] )

if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion python/GafferImageTest/ImageReaderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ def f( fileName, fileFormat, dataType, metadata, config ) :
( "exr", "openexr", "half", "" ),
( "dpx", "dpx", "uint12", "" ),
( "TIFF", "tiff", "float", "" ),
( "tif", "tiff", "uint32", str( self.openColorIOPath() / "context.ocio" ) ),
( "tif", "tiff", "uint32", ( self.openColorIOPath() / "context.ocio" ).as_posix() ),
] :

w["fileName"].setValue( self.temporaryDirectory() / "{0}.{1}".format( dataType, ext ) )
Expand Down
2 changes: 1 addition & 1 deletion python/GafferImageTest/ImageWriterTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ def f( fileName, fileFormat, dataType, metadata, config ) :
( "exr", "openexr", "half", "" ),
( "dpx", "dpx", "uint12", "" ),
( "TIFF", "tiff", "float", "" ),
( "tif", "tiff", "uint32", str( self.openColorIOPath() / "context.ocio" ) ),
( "tif", "tiff", "uint32", ( self.openColorIOPath() / "context.ocio" ).as_posix() ),
] :

w["fileName"].setValue( self.temporaryDirectory() / "{0}.{1}".format( dataType, ext ) )
Expand Down
4 changes: 2 additions & 2 deletions python/GafferImageTest/OpenColorIOAlgoTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def testCurrentConfig( self ) :

with Gaffer.Context() as c :

GafferImage.OpenColorIOAlgo.setConfig( c, str( self.openColorIOPath() / "context.ocio" ) )
GafferImage.OpenColorIOAlgo.setConfig( c, ( self.openColorIOPath() / "context.ocio" ).as_posix() )
customConfig = GafferImage.OpenColorIOAlgo.currentConfig()
self.assertIsInstance( customConfig, PyOpenColorIO.Config )
self.assertEqual( customConfig.getCacheID(), PyOpenColorIO.Config.CreateFromFile( c["ocio:config"] ).getCacheID() )
Expand All @@ -89,7 +89,7 @@ def testCurrentConfigAndContext( self ) :

with Gaffer.Context() as c :

GafferImage.OpenColorIOAlgo.setConfig( c, str( self.openColorIOPath() / "context.ocio" ) )
GafferImage.OpenColorIOAlgo.setConfig( c, ( self.openColorIOPath() / "context.ocio" ).as_posix() )
GafferImage.OpenColorIOAlgo.addVariable( c, "LUT", "srgb.spi1d" )

customConfig, customContext = GafferImage.OpenColorIOAlgo.currentConfigAndContext()
Expand Down
29 changes: 29 additions & 0 deletions python/GafferImageTest/OpenColorIOConfigPlugTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,34 @@ def testConfigAppliesDuringExecution( self ) :
with open( script["writer"]["fileName"].getValue() ) as f :
self.assertEqual( f.readlines(), [ "test.ocio, testValueA" ] )

def testContextVariableInConfigVariable( self ) :

script = Gaffer.ScriptNode()
script["variables"].addChild( Gaffer.NameValuePlug( "shot", "shot001", defaultEnabled = True, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) )

plug = GafferImage.OpenColorIOConfigPlug.acquireDefaultConfigPlug( script )
plug["config"].setValue( self.openColorIOPath() / "context.ocio" )
plug["variables"].addChild( Gaffer.NameValuePlug( "CDL", "${shot}", defaultEnabled = True, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) )

with script.context() :
ocioConfig, ocioContext = GafferImage.OpenColorIOAlgo.currentConfigAndContext()
self.assertEqual( ocioContext["CDL"], "shot001" )
hashes = { GafferImage.OpenColorIOAlgo.currentConfigAndContextHash() }

script["variables"][0]["value"].setValue( "shot002" )

with script.context() :
ocioConfig, ocioContext = GafferImage.OpenColorIOAlgo.currentConfigAndContext()
self.assertEqual( ocioContext["CDL"], "shot002" )
hashes.add( GafferImage.OpenColorIOAlgo.currentConfigAndContextHash() )
self.assertEqual( len( hashes ), 2 )

with Gaffer.Context( script.context() ) as c :
c["shot"] = "shot003"
ocioConfig, ocioContext = GafferImage.OpenColorIOAlgo.currentConfigAndContext()
self.assertEqual( ocioContext["CDL"], "shot003" )
hashes.add( GafferImage.OpenColorIOAlgo.currentConfigAndContextHash() )
self.assertEqual( len( hashes ), 3 )

if __name__ == "__main__":
unittest.main()
14 changes: 9 additions & 5 deletions src/GafferImage/OpenColorIOAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,21 @@ std::vector<std::string> GafferImage::OpenColorIOAlgo::variables( const Gaffer::
OCIO_NAMESPACE::ConstConfigRcPtr GafferImage::OpenColorIOAlgo::currentConfig()
{
const Gaffer::Context *context = Gaffer::Context::current();
return g_configCache.get( getConfig( context ) );
return g_configCache.get( context->substitute( getConfig( context ) ) );
}

IECore::MurmurHash GafferImage::OpenColorIOAlgo::currentConfigHash()
{
return Gaffer::Context::current()->variableHash( g_ocioConfigContextName );
const Gaffer::Context *context = Gaffer::Context::current();
IECore::MurmurHash result;
result.append( context->substitute( getConfig( context ) ) );
return result;
}

GafferImage::OpenColorIOAlgo::ConfigAndContext GafferImage::OpenColorIOAlgo::currentConfigAndContext()
{
const Gaffer::Context *gafferContext = Gaffer::Context::current();
OCIO_NAMESPACE::ConstConfigRcPtr config = g_configCache.get( getConfig( gafferContext ) );
OCIO_NAMESPACE::ConstConfigRcPtr config = g_configCache.get( gafferContext->substitute( getConfig( gafferContext ) ) );

OCIO_NAMESPACE::ConstContextRcPtr context = config->getCurrentContext();
OCIO_NAMESPACE::ContextRcPtr mutableContext;
Expand All @@ -198,9 +201,10 @@ GafferImage::OpenColorIOAlgo::ConfigAndContext GafferImage::OpenColorIOAlgo::cur
context = mutableContext;
}

const string value = gafferContext->substitute( gafferContext->get<string>( n ) );
mutableContext->setStringVar(
n.c_str() + g_ocioStringVarPrefix.size(),
gafferContext->get<string>( n ).c_str()
value.c_str()
);
}

Expand All @@ -219,7 +223,7 @@ IECore::MurmurHash GafferImage::OpenColorIOAlgo::currentConfigAndContextHash()
{
if( n == g_ocioConfigContextName || boost::starts_with( n.string(), g_ocioStringVarPrefix ) )
{
result.append( context->variableHash( n ) );
result.append( context->substitute( context->get<string>( n ) ) );
}
}
return result;
Expand Down
18 changes: 4 additions & 14 deletions src/GafferImage/OpenColorIOConfigPlug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,6 @@ using namespace GafferImage;
namespace
{

string substitutedValue( const StringPlug *plug )
{
string result = plug->getValue();
if( auto script = plug->ancestor<ScriptNode>() )
{
result = script->context()->substitute( result );
}
return result;
}

const IECore::InternedString g_defaultConfigPlugName( "openColorIO" );

} // namespace
Expand Down Expand Up @@ -180,8 +170,8 @@ void OpenColorIOConfigPlug::plugSet( Gaffer::Plug *plug )
auto *scriptNode = parent<ScriptNode>();
assert( scriptNode );

OpenColorIOAlgo::setConfig( scriptNode->context(), substitutedValue( configPlug() ) );
OpenColorIOAlgo::setWorkingSpace( scriptNode->context(), substitutedValue( workingSpacePlug() ) );
OpenColorIOAlgo::setConfig( scriptNode->context(), configPlug()->getValue() );
OpenColorIOAlgo::setWorkingSpace( scriptNode->context(), workingSpacePlug()->getValue() );

// Add variables

Expand All @@ -196,15 +186,15 @@ void OpenColorIOConfigPlug::plugSet( Gaffer::Plug *plug )
}
}

const string name = substitutedValue( variable->namePlug() );
const string name = scriptNode->context()->substitute( variable->namePlug()->getValue() );
if( name.empty() )
{
continue;
}

if( auto stringPlug = variable->valuePlug<StringPlug>() )
{
OpenColorIOAlgo::addVariable( scriptNode->context(), name, substitutedValue( stringPlug ) );
OpenColorIOAlgo::addVariable( scriptNode->context(), name, stringPlug->getValue() );
validVariables.insert( name );
}
else
Expand Down
Loading