Skip to content

Commit

Permalink
ShaderUI : Add _ShaderDialogue for selecting shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed May 24, 2024
1 parent 81b6713 commit a35d2fa
Showing 1 changed file with 74 additions and 25 deletions.
99 changes: 74 additions & 25 deletions python/GafferSceneUI/ShaderUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,12 @@ def headerData( self, canceller = None ) :

class _ShaderPath( Gaffer.Path ) :

def __init__( self, shaderNetworks, path, root = "/", filter = None ) :
def __init__( self, shaderNetworks, path, root = "/", filter = None, connectedParametersOnly = False ) :

Gaffer.Path.__init__( self, path, root, filter )

self.__connectedParametersOnly = connectedParametersOnly

assert( all( [ isinstance( n, IECoreScene.ShaderNetwork ) for n in shaderNetworks ] ) )

self.__shaderNetworks = shaderNetworks
Expand All @@ -458,7 +460,7 @@ def isValid( self ) :
if len( self ) > 0 and self.__shaders() is None :
return False

if len( self ) > 1 and self[1] not in self.__parameters() :
if len( self ) > 1 and self[1] not in self.__parameters():
return False

if len( self ) > 2 :
Expand Down Expand Up @@ -524,7 +526,7 @@ def property( self, name, canceller = None ) :

def copy( self ) :

return _ShaderPath( self.__shaderNetworks, self[:], self.root(), self.getFilter() )
return _ShaderPath( self.__shaderNetworks, self[:], self.root(), self.getFilter(), self.__connectedParametersOnly )

def _children( self, canceller ) :

Expand Down Expand Up @@ -560,7 +562,8 @@ def _children( self, canceller ) :
self.__shaderNetworks,
self[:] + [shaderHandle],
self.root(),
self.getFilter()
self.getFilter(),
self.__connectedParametersOnly
)
)

Expand All @@ -577,7 +580,8 @@ def _children( self, canceller ) :
self.__shaderNetworks,
self[:] + [p],
self.root(),
self.getFilter()
self.getFilter(),
self.__connectedParametersOnly
)
)

Expand All @@ -591,6 +595,14 @@ def __parameters( self ) :
if len( self ) == 0 :
return []

if self.__connectedParametersOnly :
connectedParams = set()
for n in self.__shaderNetworks :
if self[0] in n.shaders() :
for c in n.inputConnections( self[0] ) :
connectedParams.add( c.destination.name )
return list( connectedParams )

return [ p for s in self.__shaders() for p in s.parameters.keys() ]

# Returns a list of all shaders with a name matching the path's shader name.
Expand Down Expand Up @@ -717,18 +729,18 @@ def __rootPathChanged( self, path ) :

GafferUI.PathFilterWidget.registerType( _PathMatcherPathFilter, GafferUI.MatchPatternPathFilterWidget )

class _ShaderParameterDialogue( GafferUI.Dialogue ) :

def __init__( self, shaderNetworks, title = None, **kw ) :
class _ShaderDialogueBase( GafferUI.Dialogue ) :

if title is None :
title = "Select Shader Parameters"
def __init__( self, shaderNetworks, title, selectParameters, **kw ) :

GafferUI.Dialogue.__init__( self, title, **kw )

self.__selectParameters = selectParameters
self.__cancelled = False

self.__shaderNetworks = shaderNetworks

self.__path = _ShaderPath( self.__shaderNetworks, path = "/" )
self.__path = _ShaderPath( self.__shaderNetworks, path = "/", connectedParametersOnly = not self.__selectParameters )

self.__filter = _PathMatcherPathFilter( [ "" ], self.__path.copy() )
self.__filter.setEnabled( False )
Expand All @@ -749,7 +761,7 @@ def __init__( self, shaderNetworks, title = None, **kw ) :
GafferUI.PathListingWidget.StandardColumn( "Value", "shader:value" ),
_ShaderInputColumn( "Input" ),
),
allowMultipleSelection = True,
allowMultipleSelection = self.__selectParameters,
displayMode = GafferUI.PathListingWidget.DisplayMode.Tree,
sortable = False,
horizontalScrollMode = GafferUI.ScrollMode.Automatic
Expand All @@ -769,20 +781,15 @@ def __init__( self, shaderNetworks, title = None, **kw ) :
self.__confirmButton = self._addButton( "OK" )
self.__confirmButton.clickedSignal().connect( Gaffer.WeakMethod( self.__buttonClicked ), scoped = False )

self.__parametersSelectedSignal = Gaffer.Signal1()
self.__selectedSignal = Gaffer.Signal1()

self.__updateButtonState()

def parametersSelectedSignal( self ) :

return self.__parametersSelectedSignal
def _resultSelectedSignal( self ) :

# Causes the dialogue to enter a modal state, returning the selected shader parameters
# once they have been selected by the user. Returns None if the dialogue is cancelled.
# Parameters are returned as a list of tuples of the form
# [ ( "shaderName", "parameterName" ), ... ]
def waitForParameters( self, **kw ) :
return self.__selectedSignal

def _waitForResult( self, **kw ) :
if len( self.__path.children() ) == 0 :
dialogue = GafferUI.ConfirmationDialogue(
"Shader Browser",
Expand All @@ -792,7 +799,6 @@ def waitForParameters( self, **kw ) :

else :
button = self.waitForButton( **kw )

if button is self.__confirmButton :
return self.__result()

Expand All @@ -801,7 +807,7 @@ def waitForParameters( self, **kw ) :
def __buttonClicked( self, button ) :

if button is self.__confirmButton :
self.parametersSelectedSignal()( self.__result() )
self._resultSelectedSignal()( self.__result() )

def __pathSelected( self, pathListing ) :

Expand Down Expand Up @@ -840,14 +846,57 @@ def __buttonRelease( self, pathListing, event ) :
def __result( self ) :

resultPaths = self.__pathListingWidget.getSelection()

if not self.__selectParameters:
if not resultPaths.paths() or resultPaths.paths()[0].rfind( "/" ) > 0:
return None

return resultPaths.paths()[0].strip( "/" )

resultPaths = [ self.__path.copy().setFromString( x ) for x in resultPaths.paths() ]

for p in resultPaths :
if len( p ) < 2 :
return []

return [ ( p[0], p[1] ) for p in resultPaths ]

def __updateButtonState( self, *unused ) :
self.__confirmButton.setEnabled( bool( self.__result() ) )

class _ShaderParameterDialogue( _ShaderDialogueBase ) :

def __init__( self, shaderNetworks, title = None, **kw ) :

if title is None :
title = "Select Shader Parameters"

_ShaderDialogueBase.__init__( self, shaderNetworks, title, True, **kw )

# Causes the dialogue to enter a modal state, returning the selected shader parameters
# once they have been selected by the user. Returns None if the dialogue is cancelled.
# Parameters are returned as a list of tuples of the form
# [ ( "shaderName", "parameterName" ), ... ]
def waitForParameters( self, **kw ) :
return self._waitForResult( **kw )

def parametersSelectedSignal( self ) :
return self._resultSelectedSignal()



class _ShaderDialogue( _ShaderDialogueBase ) :

def __init__( self, shaderNetworks, title = None, **kw ) :

if title is None :
title = "Select Shader"

_ShaderDialogueBase.__init__( self, shaderNetworks, title, False, **kw )

# Causes the dialogue to enter a modal state, returning the handle of the selected shader once it
# has been selected by the user. Returns None if the dialogue is cancelled.
def waitForShader( self, **kw ) :
return self._waitForResult( **kw )

self.__confirmButton.setEnabled( len( self.__result() ) > 0 )
def shaderSelectedSignal( self ) :
return self._resultSelectedSignal()

0 comments on commit a35d2fa

Please sign in to comment.