Skip to content

Commit

Permalink
AttributeTweaks : Add fallback for linkedLights attribute value
Browse files Browse the repository at this point in the history
This is necessary to make `{source}` substitutions useable in all situations. As noted in the comment, we should really do this for _all_ attributes using a central registry of default values. We're just doing this one on its own because it is such high value - `linkedLights` is the main thing we had in mind when adding the `{source}` token in the first place.

Note that once we have fallbacks for all standard and renderer-specific attributes, the `ignoreMissing` plug will only be relevant for custom attributes not present in the registry. I view this as a good thing. If I make a `Multiply` tweak to double `ai:AA_samples`, it's not because I want to double it only if it exists. Rather, it's because I want to double the value that is received by the renderer.
  • Loading branch information
johnhaddon committed Apr 29, 2024
1 parent 9431519 commit 5689ceb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ Improvements
------------

- CameraTweaks : Added `ignoreMissing` plug to align behaviour with the other Tweaks nodes.
- AttributeTweaks : The `{source}` substitution for `linkedLights` now expands to `defaultLights` if the attribute doesn't exist yet. This makes tweaks such as `({source}) - unwantedLights` reliable even if no light links have been authored yet.

Breaking Changes
----------------

- CameraTweaks : `Replace` mode now errors if the input parameter does not exist. Use `Create` mode or the new `ignoreMissing` plug instead.
- TweakPlug : Remove deprecated `MissingMode::IgnoreOrReplace`.
- AttributeTweaks : `Replace` mode no longer errors if the `linkedLights` attribute doesn't exist.

1.4.x.x (relative to 1.4.1.0)
=======
Expand Down
24 changes: 24 additions & 0 deletions python/GafferSceneTest/AttributeTweaksTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,30 @@ def testCreateMode( self ) :

self.assertEqual( tweaks["out"].attributes( "/plane" )["test:attribute"], IECore.IntData( 2 ) )

def testLinkedLightsSourceSubstitution( self ) :

plane = GafferScene.Plane()

planeFilter = GafferScene.PathFilter()
planeFilter["paths"].setValue( IECore.StringVectorData( [ "/plane" ] ) )

standardAttributes = GafferScene.StandardAttributes()
standardAttributes["in"].setInput( plane["out"] )
standardAttributes["filter"].setInput( planeFilter["out"] )

self.assertNotIn( "linkedLights", standardAttributes["out"].attributes( "/plane" ) )

tweaks = GafferScene.AttributeTweaks()
tweaks["in"].setInput( standardAttributes["out"] )
tweaks["filter"].setInput( planeFilter["out"] )

testTweak = Gaffer.TweakPlug( "linkedLights", "({source}) - unwantedLights" )
tweaks["tweaks"].addChild( testTweak )
self.assertEqual( tweaks["out"].attributes( "/plane" )["linkedLights"], IECore.StringData( "(defaultLights) - unwantedLights" ) )

standardAttributes["attributes"]["linkedLights"]["enabled"].setValue( True )
standardAttributes["attributes"]["linkedLights"]["value"].setValue( "someLights" )
self.assertEqual( tweaks["out"].attributes( "/plane" )["linkedLights"], IECore.StringData( "(someLights) - unwantedLights" ) )

if __name__ == "__main__" :
unittest.main()
20 changes: 17 additions & 3 deletions src/GafferScene/AttributeTweaks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;

namespace
{

const ConstStringDataPtr g_linkedLightsDefault = new StringData( "defaultLights" );

} // namespace

GAFFER_NODE_DEFINE_TYPE( AttributeTweaks );

size_t AttributeTweaks::g_firstPlugIndex = 0;
Expand Down Expand Up @@ -147,9 +154,16 @@ IECore::ConstCompoundObjectPtr AttributeTweaks::computeProcessedAttributes( cons
}

tweaksPlug->applyTweaks(
[&source]( const std::string &valueName )
[&source]( const std::string &valueName ) -> const IECore::Data *
{
return source->member<Data>( valueName );
const Data *result = source->member<Data>( valueName );
if( !result && valueName == "linkedLights" )
{
/// \todo Use a registry to provide default values for
/// all attributes.
return g_linkedLightsDefault.get();
}
return result;
},
[&result]( const std::string &valueName, DataPtr newData )
{
Expand All @@ -164,4 +178,4 @@ IECore::ConstCompoundObjectPtr AttributeTweaks::computeProcessedAttributes( cons
);

return result;
}
}

0 comments on commit 5689ceb

Please sign in to comment.