Skip to content

Commit

Permalink
RenderPassEditor : Display adaptor disabled render passes
Browse files Browse the repository at this point in the history
Pipelines can register render adaptors to `client = "RenderPassWedge"` that
disable render passes. We want to display the state of these to the user
and distinguish them from regular user-disabled render passes.
  • Loading branch information
murraystevenson authored and johnhaddon committed Jan 17, 2025
1 parent 4535963 commit 6fb8249
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 5 deletions.
1 change: 1 addition & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,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 : 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.

Fixes
-----
Expand Down
42 changes: 40 additions & 2 deletions python/GafferSceneUI/RenderPassEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ def __init__( self ) :
self["editScope"] = Gaffer.Plug()
self["displayGrouped"] = Gaffer.BoolPlug()

self["__adaptors"] = GafferSceneUI.RenderPassEditor._createRenderAdaptors()
self["__adaptors"]["in"].setInput( self["in"] )

self["__adaptedIn"] = GafferScene.ScenePlug()
self["__adaptedIn"].setInput( self["__adaptors"]["out"] )

IECore.registerRunTimeTyped( Settings, typeName = "GafferSceneUI::RenderPassEditor::Settings" )

def __init__( self, scriptNode, **kw ) :
Expand Down Expand Up @@ -236,7 +242,19 @@ def _createRenderAdaptors() :
adaptors["__renderAdaptors"]["client"].setValue( "RenderPassWedge" )
adaptors["__renderAdaptors"]["in"].setInput( adaptors["in"] )

adaptors["out"].setInput( adaptors["__renderAdaptors"]["out"] )
adaptors["__adaptorSwitch"] = Gaffer.Switch()
adaptors["__adaptorSwitch"].setup( GafferScene.ScenePlug() )
adaptors["__adaptorSwitch"]["in"]["in0"].setInput( adaptors["__renderAdaptors"]["out"] )
adaptors["__adaptorSwitch"]["in"]["in1"].setInput( adaptors["in"] )

adaptors["__contextQuery"] = Gaffer.ContextQuery()
adaptors["__contextQuery"].addQuery( Gaffer.BoolPlug( "disableAdaptors", defaultValue = False ) )
adaptors["__contextQuery"]["queries"][0]["name"].setValue( "renderPassEditor:disableAdaptors" )

adaptors["__adaptorSwitch"]["index"].setInput( adaptors["__contextQuery"]["out"][0]["value"] )
adaptors["__adaptorSwitch"]["deleteContextVariables"].setValue( "renderPassEditor:disableAdaptors" )

adaptors["out"].setInput( adaptors["__adaptorSwitch"]["out"] )

return adaptors

Expand Down Expand Up @@ -281,7 +299,7 @@ def __setPathListingPath( self ) :
# control of updates ourselves in _updateFromContext(), using LazyMethod to defer the calls to this
# function until we are visible and playback has stopped.
contextCopy = Gaffer.Context( self.context() )
self.__pathListing.setPath( _GafferSceneUI._RenderPassEditor.RenderPassPath( self.settings()["in"], contextCopy, "/", filter = self.__filter, grouped = self.settings()["displayGrouped"].getValue() ) )
self.__pathListing.setPath( _GafferSceneUI._RenderPassEditor.RenderPassPath( self.settings()["__adaptedIn"], contextCopy, "/", filter = self.__filter, grouped = self.settings()["displayGrouped"].getValue() ) )

def __displayGroupedChanged( self ) :

Expand Down Expand Up @@ -1015,8 +1033,13 @@ def _valuesForUpdate( plugs, auxiliaryPlugs ) :
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 :
renderPasses.setdefault( "enabled", [] ).append( renderPass )
else :
context["renderPassEditor:disableAdaptors"] = True
if globalsPlug.getValue().get( "option:renderPass:enabled", IECore.BoolData( True ) ).value :
renderPasses.setdefault( "adaptorDisabled", [] ).append( renderPass )

result.append( {
"value" : plug.getValue(),
Expand Down Expand Up @@ -1079,6 +1102,7 @@ def __menuDefinition( self ) :
{
"command" : functools.partial( Gaffer.WeakMethod( self.__setCurrentRenderPass ), name ),
"icon" : self.__renderPassIcon( name, activeIndicator = True ),
"description" : self.__renderPassDescription( name )
}
)

Expand Down Expand Up @@ -1123,6 +1147,18 @@ def __setCurrentRenderPass( self, renderPass, *unused ) :
for plug in self.getPlugs() :
plug.setValue( renderPass )

def __renderPassDescription( self, renderPass ) :

if renderPass == "" :
return ""

if renderPass in self.__renderPasses.get( "adaptorDisabled", [] ) :
return "{} has been automatically disabled by a render adaptor.".format( renderPass )
elif renderPass not in self.__renderPasses.get( "enabled", [] ) :
return "{} has been disabled.".format( renderPass )

return ""

def __renderPassIcon( self, renderPass, activeIndicator = False ) :

if renderPass == "" :
Expand All @@ -1134,6 +1170,8 @@ def __renderPassIcon( self, renderPass, activeIndicator = False ) :
return "warningSmall.png"
elif renderPass in self.__renderPasses.get( "enabled", [] ) :
return "renderPass.png"
elif renderPass in self.__renderPasses.get( "adaptorDisabled", [] ) :
return "adaptorDisabledRenderPass.png"
else :
return "disabledRenderPass.png"

Expand Down
41 changes: 41 additions & 0 deletions python/GafferSceneUITest/RenderPassEditorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,47 @@ def testFn( name ) :
else :
self.assertIsNone( inspectionContext )

def testRenderPassPathAdaptorDisablingPasses( self ) :

def createAdaptor() :

node = GafferScene.SceneProcessor()
node["options"] = GafferScene.CustomOptions()
node["options"]["in"].setInput( node["in"] )
node["options"]["options"].addChild( Gaffer.NameValuePlug( "renderPass:enabled", False ) )

node["switch"] = Gaffer.NameSwitch()
node["switch"].setup( node["options"]["out"] )
node["switch"]["in"][0]["value"].setInput( node["in"] )
node["switch"]["in"][1]["value"].setInput( node["options"]["out"] )
node["switch"]["in"][1]["name"].setValue( "B C" )
node["switch"]["selector"].setValue( "${renderPass}" )

node["out"].setInput( node["switch"]["out"]["value"] )

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
1 change: 1 addition & 0 deletions resources/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@
"ids" : [
"renderPass",
"disabledRenderPass",
"adaptorDisabledRenderPass",
"renderPassFolder",
"activeRenderPass",
"activeRenderPassFadedHighlighted",
Expand Down
34 changes: 34 additions & 0 deletions resources/graphics.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 31 additions & 3 deletions src/GafferSceneUIModule/RenderPassEditorBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ using PathMatcherCache = IECorePreview::LRUCache<IECore::MurmurHash, IECore::Pat
PathMatcherCache g_pathMatcherCache( pathMatcherCacheGetter, 25 );

const InternedString g_renderPassContextName( "renderPass" );
const InternedString g_disableAdaptorsContextName( "renderPassEditor:disableAdaptors" );
const InternedString g_renderPassNamePropertyName( "renderPassPath:name" );
const InternedString g_renderPassEnabledPropertyName( "renderPassPath:enabled" );
const InternedString g_renderPassEnabledWithoutAdaptorsPropertyName( "renderPassPath:enabledWithoutAdaptors" );
const InternedString g_renderPassNamesOption( "option:renderPass:names" );
const InternedString g_renderPassEnabledOption( "option:renderPass:enabled" );

Expand Down Expand Up @@ -303,6 +305,7 @@ class RenderPassPath : public Gaffer::Path
Path::propertyNames( names, canceller );
names.push_back( g_renderPassNamePropertyName );
names.push_back( g_renderPassEnabledPropertyName );
names.push_back( g_renderPassEnabledWithoutAdaptorsPropertyName );
}

IECore::ConstRunTimeTypedPtr property( const IECore::InternedString &name, const IECore::Canceller *canceller = nullptr ) const override
Expand All @@ -315,12 +318,17 @@ class RenderPassPath : public Gaffer::Path
return new StringData( names().back().string() );
}
}
else if( name == g_renderPassEnabledPropertyName )
else if( name == g_renderPassEnabledPropertyName || name == g_renderPassEnabledWithoutAdaptorsPropertyName )
{
const PathMatcher p = pathMatcher( canceller );
if( p.match( names() ) & PathMatcher::ExactMatch )
{
Context::EditableScope scopedContext( getContext() );
if( name == g_renderPassEnabledWithoutAdaptorsPropertyName )
{
const bool disableAdaptors = true;
scopedContext.set<bool>( g_disableAdaptorsContextName, &disableAdaptors );
}
if( canceller )
{
scopedContext.setCanceller( canceller );
Expand Down Expand Up @@ -452,9 +460,12 @@ RenderPassPath::Ptr constructor2( ScenePlug &scene, Context &context, const std:
// RenderPassNameColumn
//////////////////////////////////////////////////////////////////////////

ConstStringDataPtr g_adaptorDisabledRenderPassIcon = new StringData( "adaptorDisabledRenderPass.png" );
ConstStringDataPtr g_disabledRenderPassIcon = new StringData( "disabledRenderPass.png" );
ConstStringDataPtr g_renderPassIcon = new StringData( "renderPass.png" );
ConstStringDataPtr g_renderPassFolderIcon = new StringData( "renderPassFolder.png" );
ConstStringDataPtr g_disabledToolTip = new StringData( "Disabled." );
ConstStringDataPtr g_adaptorDisabledToolTip = new StringData( "Automatically disabled by a render adaptor.");
const Color4fDataPtr g_dimmedForegroundColor = new Color4fData( Imath::Color4f( 152, 152, 152, 255 ) / 255.0f );

class RenderPassNameColumn : public StandardPathColumn
Expand Down Expand Up @@ -482,8 +493,25 @@ class RenderPassNameColumn : public StandardPathColumn
{
if( const auto renderPassEnabled = runTimeCast<const IECore::BoolData>( path.property( g_renderPassEnabledPropertyName, canceller ) ) )
{
result.icon = renderPassEnabled->readable() ? g_renderPassIcon : g_disabledRenderPassIcon;
result.foreground = renderPassEnabled->readable() ? nullptr : g_dimmedForegroundColor;
if( renderPassEnabled->readable() )
{
result.icon = g_renderPassIcon;
}
else
{
result.foreground = g_dimmedForegroundColor;
const auto renderPassEnabledWithoutAdaptors = runTimeCast<const IECore::BoolData>( path.property( g_renderPassEnabledWithoutAdaptorsPropertyName, canceller ) );
if( !renderPassEnabledWithoutAdaptors || !renderPassEnabledWithoutAdaptors->readable() )
{
result.icon = g_disabledRenderPassIcon;
result.toolTip = g_disabledToolTip;
}
else
{
result.icon = g_adaptorDisabledRenderPassIcon;
result.toolTip = g_adaptorDisabledToolTip;
}
}
}
else
{
Expand Down

0 comments on commit 6fb8249

Please sign in to comment.