Skip to content

Commit

Permalink
Merge pull request #6219 from murraystevenson/renderPassEditorColumnI…
Browse files Browse the repository at this point in the history
…ndex

RenderPassEditor : Support registering columns with a specific index
  • Loading branch information
johnhaddon authored Jan 21, 2025
2 parents f1380ea + 5ac2886 commit 8524c13
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 6 deletions.
5 changes: 5 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Fixes
- Fixed warning messages when attempting to disable a non-existent edit.
- Fixed warning message which referred to "None" rather than the "Source" scope.

API
---

- RenderPassEditor : Added optional `index` argument to `registerOption()` and `registerColumn()`. This can be used to specify the column's position in the UI.

1.5.3.0 (relative to 1.5.2.0)
=======

Expand Down
30 changes: 24 additions & 6 deletions python/GafferSceneUI/RenderPassEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def __init__( self, scriptNode, **kw ) :
__columnRegistry = collections.OrderedDict()

@classmethod
def registerOption( cls, groupKey, optionName, section = "Main", columnName = None ) :
def registerOption( cls, groupKey, optionName, section = "Main", columnName = None, index = None ) :

optionLabel = Gaffer.Metadata.value( "option:" + optionName, "label" )
if not columnName :
Expand All @@ -173,20 +173,21 @@ def registerOption( cls, groupKey, optionName, section = "Main", columnName = No
columnName,
toolTip
),
section
section,
index
)

# Registers a column in the Render Pass Editor.
# `inspectorFunction` is a callable object of the form
# `inspectorFunction( scene, editScope )` returning a
# `GafferSceneUI.Private.InspectorColumn` object.
@classmethod
def registerColumn( cls, groupKey, columnKey, inspectorFunction, section = "Main" ) :
def registerColumn( cls, groupKey, columnKey, inspectorFunction, section = "Main", index = None ) :

sections = cls.__columnRegistry.setdefault( groupKey, collections.OrderedDict() )
section = sections.setdefault( section, collections.OrderedDict() )

section[columnKey] = inspectorFunction
section[columnKey] = ( inspectorFunction, index )

@classmethod
def deregisterColumn( cls, groupKey, columnKey, section = "Main" ) :
Expand Down Expand Up @@ -287,9 +288,26 @@ def __updateColumns( self ) :
for groupKey, sections in self.__columnRegistry.items() :
if IECore.StringAlgo.match( tabGroup, groupKey ) :
section = sections.get( currentSection or None, {} )
sectionColumns += [ c( self.settings()["in"], self.settings()["editScope"] ) for c in section.values() ]
sectionColumns += [ ( c( self.settings()["in"], self.settings()["editScope"] ), index ) for ( c, index ) in section.values() ]

self.__pathListing.setColumns( [ self.__renderPassNameColumn, self.__renderPassActiveColumn ] + sectionColumns )
self.__pathListing.setColumns( [ self.__renderPassNameColumn, self.__renderPassActiveColumn ] + self.__orderedColumns( sectionColumns ) )

@staticmethod
def __orderedColumns( columnsAndIndices ) :

for i, ( column, index ) in enumerate( columnsAndIndices ) :
if index is not None :
# Negative indices are remapped to their absolute position in the column list.
columnsAndIndices[i] = ( column, index if index >= 0 else len( columnsAndIndices ) + index )

# As column indices may be sparse, we fill in the gaps with any unspecified indices before sorting.
availableIndices = iter( sorted( set( range( len( columnsAndIndices ) ) ) - { x[1] for x in columnsAndIndices } ) )
orderedColumns = sorted(
[ ( column, index if index is not None else next( availableIndices ) ) for column, index in columnsAndIndices ],
key = lambda x: x[1]
)

return [ x[0] for x in orderedColumns ]

@GafferUI.LazyMethod( deferUntilPlaybackStops = True )
def __setPathListingPath( self ) :
Expand Down
109 changes: 109 additions & 0 deletions python/GafferSceneUITest/RenderPassEditorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,112 @@ def testFn( name ) :
self.assertEqual( [ str( c ) for c in path.children() ], [ "/A/A_A", "/A/A_B" ] )
path.setFromString( "/B" )
self.assertEqual( [ str( c ) for c in path.children() ], [ "/B/B_C", "/B/B_D" ] )

def testRegisterOption( self ) :

for columnName in [ "A", "B", "C", "D", "E" ] :
GafferSceneUI.RenderPassEditor.registerOption( "*", columnName, "Test" )
self.addCleanup( GafferSceneUI.RenderPassEditor.deregisterColumn, "*", columnName, "Test" )

script = Gaffer.ScriptNode()

editor = GafferSceneUI.RenderPassEditor( script )
editor.settings()["section"].setValue( "Test" )

GafferSceneUI.RenderPassEditor._RenderPassEditor__updateColumns.flush( editor )

pathListing = editor._RenderPassEditor__pathListing

columnNames = [ c.headerData().value for c in pathListing.getColumns() ]
for columnName in [ "A", "B", "C", "D", "E" ] :
self.assertIn( columnName, columnNames )

GafferSceneUI.RenderPassEditor.deregisterColumn( "*", "B", "Test" )

editor._RenderPassEditor__updateColumns()
GafferSceneUI.RenderPassEditor._RenderPassEditor__updateColumns.flush( editor )

columnNames = [ c.headerData().value for c in pathListing.getColumns() ]
self.assertNotIn( "B", columnNames )
self.assertIn( "A", columnNames )
self.assertIn( "C", columnNames )
self.assertIn( "D", columnNames )
self.assertIn( "E", columnNames )

def testColumnOrder( self ) :

script = Gaffer.ScriptNode()
editor = GafferSceneUI.RenderPassEditor( script )
editor.settings()["section"].setValue( "Test" )

def assertColumnOrder( columns, order ) :

for columnName, index in columns :
GafferSceneUI.RenderPassEditor.registerOption( "*", columnName, "Test", index = index )
self.addCleanup( GafferSceneUI.RenderPassEditor.deregisterColumn, "*", columnName, "Test" )

editor._RenderPassEditor__updateColumns()
GafferSceneUI.RenderPassEditor._RenderPassEditor__updateColumns.flush( editor )
columnNames = [ c.headerData().value for c in editor._RenderPassEditor__pathListing.getColumns() if isinstance( c, GafferSceneUI.Private.InspectorColumn ) ]
self.assertEqual( columnNames, order )

for columnName, _ in columns :
GafferSceneUI.RenderPassEditor.deregisterColumn( "*", columnName, "Test" )

assertColumnOrder(
[ ( "A", None ), ( "B", None ), ( "C", None ), ( "D", None ), ( "E", None ) ],
[ "A", "B", "C", "D", "E" ]
)

assertColumnOrder(
[ ( "E", None ), ( "D", None ), ( "C", None ), ( "B", None ), ( "A", None ) ],
[ "E", "D", "C", "B", "A" ]
)

assertColumnOrder(
[ ( "A", 0 ), ( "B", 1 ), ( "C", 2 ), ( "D", 3 ), ( "E", 4 ) ],
[ "A", "B", "C", "D", "E" ]
)

assertColumnOrder(
[ ( "A", 4 ), ( "B", 3 ), ( "C", 2 ), ( "D", 1 ), ( "E", 0 ) ],
[ "E", "D", "C", "B", "A" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", None ), ( "C", None ), ( "D", 0 ), ( "E", 2 ) ],
[ "D", "A", "E", "B", "C" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", None ), ( "C", 0 ), ( "D", -1 ), ( "E", None ) ],
[ "C", "A", "B", "E", "D" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", None ), ( "C", -1 ), ( "D", -2 ), ( "E", None ) ],
[ "A", "B", "E", "D", "C" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", -1 ), ( "C", None ), ( "D", -1 ), ( "E", None ) ],
[ "A", "C", "E", "B", "D" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", 0 ), ( "C", 0 ), ( "D", None ), ( "E", 2 ) ],
[ "B", "C", "A", "E", "D" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", 0 ), ( "C", 0 ), ( "D", 0 ), ( "E", 2 ) ],
[ "B", "C", "D", "A", "E" ]
)

assertColumnOrder(
[ ( "A", None ), ( "B", 0 ), ( "C", 0 ), ( "D", 0 ), ( "E", 1 ) ],
[ "B", "C", "D", "E", "A" ]
)

if __name__ == "__main__" :
unittest.main()

0 comments on commit 8524c13

Please sign in to comment.