Skip to content

Commit

Permalink
RenderPassEditor : Display adaptor deleted render passes as disabled
Browse files Browse the repository at this point in the history
As render passes could have been deleted by a render adaptor, we build our
RenderPassPaths from a PathMatcher generated with the render adaptors disabled
and then later test to see whether the render pass still exists with adaptors enabled.

From the end user's perspective, there's no functional difference between render
passes deleted or disabled by a render adaptor, so we present both as automatically
disabled.
  • Loading branch information
murraystevenson committed Dec 10, 2024
1 parent a39941a commit b40973a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Improvements
- PlugLayout :
- A warning widget is now displayed when an invalid custom widget is registered.
- `layout:customWidget:<name>:width` and `layout:customWidget:<name>:minimumWidth` metadata registrations are now supported for custom widgets.
- RenderPassEditor / RenderPassChooserWidget : Render passes disabled by render adaptors registered to `client = "RenderPassWedge"` are now shown as disabled. To differentiate these from user disabled render passes, an orange dot is shown in the corner of the disabled icon and the tooltip describes them as automatically disabled.
- RenderPassEditor / RenderPassChooserWidget : Render passes deleted or disabled by render adaptors registered to `client = "RenderPassWedge"` are now shown as disabled. To differentiate these from user disabled render passes, an orange dot is shown in the corner of the disabled icon and the tooltip describes them as automatically disabled.

Fixes
-----
Expand Down
7 changes: 6 additions & 1 deletion python/GafferSceneUI/RenderPassEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,11 +1036,16 @@ def _valuesForUpdate( plugs, auxiliaryPlugs ) :
renderPasses = {}

with Gaffer.Context( Gaffer.Context.current() ) as context :
adaptedRenderPassNames = globalsPlug.getValue().get( "option:renderPass:names", IECore.StringVectorData() )
context["renderPassEditor:disableAdaptors"] = True
for renderPass in globalsPlug.getValue().get( "option:renderPass:names", IECore.StringVectorData() ) :
renderPasses.setdefault( "all", [] ).append( renderPass )
context["renderPass"] = renderPass
context["renderPassEditor:disableAdaptors"] = False
if globalsPlug.getValue().get( "option:renderPass:enabled", IECore.BoolData( True ) ).value :
if renderPass not in adaptedRenderPassNames :
# The render pass has been deleted by a render adaptor so present it as disabled
renderPasses.setdefault( "adaptorDisabled", [] ).append( renderPass )
elif globalsPlug.getValue().get( "option:renderPass:enabled", IECore.BoolData( True ) ).value :
renderPasses.setdefault( "enabled", [] ).append( renderPass )
else :
context["renderPassEditor:disableAdaptors"] = True
Expand Down
29 changes: 29 additions & 0 deletions python/GafferSceneUITest/RenderPassEditorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,35 @@ def createAdaptor() :
self.assertEqual( pathCopy.property( "renderPassPath:enabled" ), p in ( "/A", "/D" ) )
self.assertTrue( pathCopy.property( "renderPassPath:enabledWithoutAdaptors" ) )

def testRenderPassPathAdaptorDeletingPasses( self ) :

def createAdaptor() :

node = GafferScene.DeleteRenderPasses()
node["names"].setValue( "B C" )
return node

GafferScene.SceneAlgo.registerRenderAdaptor( "RenderPassEditorTest", createAdaptor, client = "RenderPassWedge" )
self.addCleanup( GafferScene.SceneAlgo.deregisterRenderAdaptor, "RenderPassEditorTest" )

renderPasses = GafferScene.RenderPasses()
renderPasses["names"].setValue( IECore.StringVectorData( [ "A", "B", "C", "D" ] ) )

adaptors = GafferSceneUI.RenderPassEditor._createRenderAdaptors()
adaptors["in"].setInput( renderPasses["out"] )

context = Gaffer.Context()
path = _GafferSceneUI._RenderPassEditor.RenderPassPath( adaptors["out"], context, "/" )

self.assertEqual( [ str( c ) for c in path.children() ], [ "/A", "/B", "/C", "/D" ] )

pathCopy = path.copy()

for p in [ "/A", "/B", "/C", "/D" ] :
pathCopy.setFromString( p )
self.assertEqual( pathCopy.property( "renderPassPath:enabled" ), p in ( "/A", "/D" ) )
self.assertTrue( pathCopy.property( "renderPassPath:enabledWithoutAdaptors" ) )

def testSearchFilter( self ) :

renderPasses = GafferScene.RenderPasses()
Expand Down
17 changes: 15 additions & 2 deletions src/GafferSceneUIModule/RenderPassEditorBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ PathMatcher pathMatcherCacheGetter( const PathMatcherCacheGetterKey &key, size_t
}

using PathMatcherCache = IECorePreview::LRUCache<IECore::MurmurHash, IECore::PathMatcher, IECorePreview::LRUCachePolicy::Parallel, PathMatcherCacheGetterKey>;
PathMatcherCache g_pathMatcherCache( pathMatcherCacheGetter, 25 );
PathMatcherCache g_pathMatcherCache( pathMatcherCacheGetter, 50 );

const InternedString g_renderPassContextName( "renderPass" );
const InternedString g_disableAdaptorsContextName( "renderPassEditor:disableAdaptors" );
Expand Down Expand Up @@ -320,6 +320,15 @@ class RenderPassPath : public Gaffer::Path
}
else if( name == g_renderPassEnabledPropertyName || name == g_renderPassEnabledWithoutAdaptorsPropertyName )
{
if(
name == g_renderPassEnabledPropertyName &&
!( pathMatcher( canceller, /* disableAdaptors = */ false ).match( names() ) & PathMatcher::ExactMatch )
)
{
// The render pass has been deleted by a render adaptor, so present it to the user as disabled.
return new BoolData( false );
}

const PathMatcher p = pathMatcher( canceller );
if( p.match( names() ) & PathMatcher::ExactMatch )
{
Expand Down Expand Up @@ -402,14 +411,18 @@ class RenderPassPath : public Gaffer::Path
// practical as render pass names are used in output file paths where the included '/' characters would be
// interpreted as subdirectories. Validation in the UI will prevent users from inserting invalid characters
// such as '/' into render pass names.
const IECore::PathMatcher pathMatcher( const IECore::Canceller *canceller ) const
const IECore::PathMatcher pathMatcher( const IECore::Canceller *canceller, bool disableAdaptors = true ) const
{
Context::EditableScope scopedContext( m_context.get() );
if( canceller )
{
scopedContext.setCanceller( canceller );
}

if( disableAdaptors )
{
scopedContext.set<bool>( g_disableAdaptorsContextName, &disableAdaptors );
}
if( ConstStringVectorDataPtr renderPassData = m_scene.get()->globals()->member<StringVectorData>( g_renderPassNamesOption ) )
{
const PathMatcherCacheGetterKey key( renderPassData, m_grouped );
Expand Down

0 comments on commit b40973a

Please sign in to comment.