Skip to content

Commit

Permalink
Merge pull request #5871 from murraystevenson/optionsMetadata
Browse files Browse the repository at this point in the history
OptionTweaks / Spreadsheet / Render Pass Editor : Make use of metadata registered for options
  • Loading branch information
johnhaddon authored May 29, 2024
2 parents 4fa84b2 + 4a8f20e commit 8653221
Show file tree
Hide file tree
Showing 10 changed files with 382 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Improvements
- SetFilter, StandardAttributes, StandardOptions : Added syntax highlighting and auto-complete for set expressions.
- NodeEditor, UIEditor, PythonEditor : Added popup hint for the <kbd>Ctrl</kbd>+<kbd>Return</kbd> shortcut.
- CodeWidget : Added highlighting of braces and operators.
- RenderPassEditor : Added preset menu for choosing a render pass type from the list of available registered types. An "auto" type is included in the list when an auto type function has been registered.
- OptionTweaks : Tweak `value` plugs can now access metadata registered globally to `option:{tweakName}`, where `{tweakName}` is the value of the tweak's `name` plug.
- Spreadsheet : Added support for metadata to be automatically forwarded from plugs downstream of a column's `out` plug to the column's default row.

Fixes
-----
Expand Down Expand Up @@ -40,6 +43,7 @@ API
- TextWidget : Added `selectedText()` convenience method.
- MultiLineTextWidget : Added `setSelection()` and `getSelection()` methods.
- SetExpressionPlugValueWidget : Added new editor for set expressions, with syntax highlighting and auto-complete.
- RenderPassTypeAdaptor : Added `autoTypeFunction()` method.

1.4.4.0 (relative to 1.4.3.0)
=======
Expand Down
5 changes: 5 additions & 0 deletions python/GafferScene/RenderPassTypeAdaptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ def registerAutoTypeFunction( cls, f ) :

cls.__autoTypeFunction = f

@classmethod
def autoTypeFunction( cls ) :

return cls.__autoTypeFunction

@classmethod
def resolvedType( cls, type, name ) :

Expand Down
47 changes: 47 additions & 0 deletions python/GafferSceneUI/OptionTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,41 @@
import GafferUI
import GafferScene

def __optionMetadata( plug, name ) :

option = plug.ancestor( Gaffer.TweakPlug )["name"].getValue()
return Gaffer.Metadata.value( "option:{}".format( option ), name )

def __optionMetadataPresets( plug ) :

result = collections.OrderedDict()
option = plug.ancestor( Gaffer.TweakPlug )["name"].getValue()
source = "option:{}".format( option )

for n in Gaffer.Metadata.registeredValues( source ) :
if n.startswith( "preset:" ) :
result[n[7:]] = Gaffer.Metadata.value( source, n )

presetNames = Gaffer.Metadata.value( source, "presetNames" )
presetValues = Gaffer.Metadata.value( source, "presetValues" )
if presetNames and presetValues :
for presetName, presetValue in zip( presetNames, presetValues ) :
result.setdefault( presetName, presetValue )

return result

def __optionMetadataPresetNames( plug ) :

names = list( __optionMetadataPresets( plug ).keys() )

return IECore.StringVectorData( names ) if names else None

def __optionMetadataPresetValues( plug ) :

values = list( __optionMetadataPresets( plug ).values() )

return IECore.DataTraits.dataFromElement( values ) if values else None

Gaffer.Metadata.registerNode(

GafferScene.OptionTweaks,
Expand Down Expand Up @@ -89,6 +124,18 @@

],

"tweaks.*.value" : [

"description", functools.partial( __optionMetadata, name = "description" ),
"plugValueWidget:type", functools.partial( __optionMetadata, name = "plugValueWidget:type" ),
"presetsPlugValueWidget:allowCustom", functools.partial( __optionMetadata, name = "presetsPlugValueWidget:allowCustom" ),
"ui:scene:acceptsSetExpression", functools.partial( __optionMetadata, name = "ui:scene:acceptsSetExpression" ),

"presetNames", __optionMetadataPresetNames,
"presetValues", __optionMetadataPresetValues,

],

}
)

Expand Down
19 changes: 19 additions & 0 deletions python/GafferSceneUI/RenderPassTypeAdaptorUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,28 @@
#
##########################################################################

import IECore

import Gaffer
import GafferScene

def __renderPassTypes() :

types = sorted( list( GafferScene.RenderPassTypeAdaptor.registeredTypeNames() ) )

if callable( GafferScene.RenderPassTypeAdaptor.autoTypeFunction() ) :
types.insert( 0, "auto" )

return types

def renderPassTypePresetNames() :

return IECore.StringVectorData( [ IECore.CamelCase.toSpaced( p ) for p in __renderPassTypes() ] )

def renderPassTypePresetValues() :

return IECore.StringVectorData( __renderPassTypes() )

Gaffer.Metadata.registerNode(

GafferScene.RenderPassTypeAdaptor,
Expand Down
2 changes: 1 addition & 1 deletion python/GafferSceneUI/RenderUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

from GafferUI.PlugValueWidget import sole

def rendererPresetNames( plug ) :
def rendererPresetNames( plug = None ) :

blacklist = { "Capturing" }
return IECore.StringVectorData(
Expand Down
20 changes: 16 additions & 4 deletions python/GafferUI/PlugPopup.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def __init__( self, plugs, title = None, warning = None, **kw ) :
colorPlugValueWidget.setColorChooserVisible( True )

self.visibilityChangedSignal().connect( Gaffer.WeakMethod( self.__visibilityChanged ), scoped = False )
self.focusChangedSignal().connect( Gaffer.WeakMethod( self.__focusChanged ), scoped = False )

def popup( self, center = None ) :

Expand Down Expand Up @@ -154,6 +155,19 @@ def __visibilityChanged( self, unused ) :
if gafferWidget is not None and self.isAncestorOf( gafferWidget ) :
gafferWidget._qtWidget().clearFocus()

def __focusChanged( self, oldWidget, newWidget ) :

if self.__plugValueWidget.isAncestorOf( newWidget ) and hasattr( newWidget, "activatedSignal" ) :
self.__widgetActivatedConnection = newWidget.activatedSignal().connect(
Gaffer.WeakMethod( self.__activated ), scoped = True
)
else :
self.__widgetActivatedConnection = None

def __activated( self, unused ) :

self.close()

@classmethod
def __firstTextWidget( cls, plugValueWidget ) :

Expand All @@ -165,13 +179,11 @@ def widgetUsable( w ) :

widget = None

if isinstance( plugValueWidget, GafferUI.StringPlugValueWidget ) :
widget = plugValueWidget.textWidget()
elif isinstance( plugValueWidget, GafferUI.NumericPlugValueWidget ) :
if isinstance( plugValueWidget, GafferUI.NumericPlugValueWidget ) :
widget = plugValueWidget.numericWidget()
elif isinstance( plugValueWidget, GafferUI.PathPlugValueWidget ) :
widget = plugValueWidget.pathWidget()
elif isinstance( plugValueWidget, GafferUI.MultiLineStringPlugValueWidget ) :
elif hasattr( plugValueWidget, "textWidget" ) :
widget = plugValueWidget.textWidget()

if widget is not None and widgetUsable( widget ) :
Expand Down
80 changes: 68 additions & 12 deletions python/GafferUI/SpreadsheetUI/_Metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,30 @@ def __correspondingDefaultPlug( plug ) :
rowsPlug = rowPlug.parent()
return rowsPlug.defaultRow().descendant( plug.relativeName( rowPlug ) )

def __correspondingOutPlug( plug ) :

return Gaffer.PlugAlgo.findDestination(
plug,
lambda p : p if isinstance( p.node(), Gaffer.Spreadsheet ) and p.node()["out"].isAncestorOf( p ) else None
)

def __defaultCellMetadata( plug, key ) :

return Gaffer.Metadata.value( __correspondingDefaultPlug( plug ), key )

def __forwardedMetadata( plug, key ) :

# We begin this search from the corresponding out plug as `findDestination`
# evaluates our metadata check from the provided plug onwards. Starting this
# search from a plug where `__forwardedMetadata` has been registered would
# result in infinite recursion, so we begin our search downstream.
source = Gaffer.PlugAlgo.findDestination(
__correspondingOutPlug( plug ),
lambda p : p if Gaffer.Metadata.value( p, key ) else None
)

return Gaffer.Metadata.value( source, key ) if source else None

for key in [
"description",
"spreadsheet:columnLabel",
Expand All @@ -263,6 +283,10 @@ def __defaultCellMetadata( plug, key ) :
"tweakPlugValueWidget:allowCreate",
] :

Gaffer.Metadata.registerValue(
Gaffer.Spreadsheet.RowsPlug, "default.cells.*...", key,
functools.partial( __forwardedMetadata, key = key ),
)
Gaffer.Metadata.registerValue(
Gaffer.Spreadsheet.RowsPlug, "row*.*...", key,
functools.partial( __defaultCellMetadata, key = key ),
Expand All @@ -286,36 +310,68 @@ def __defaultCellMetadata( plug, key ) :

}

def __presetSourcePlug( plug ) :

def predicate( p ) :

if (
( Gaffer.Metadata.value( p, "presetNames" ) and Gaffer.Metadata.value( p, "presetValues" ) )
or any( v.startswith( "preset:" ) for v in Gaffer.Metadata.registeredValues( p ) )
) :
return p

return Gaffer.PlugAlgo.findDestination(
__correspondingOutPlug( plug ),
lambda p : predicate( p )
)

def __presetNamesMetadata( plug ) :

if plug.__class__ not in __plugPresetTypes :
if not plug or plug.__class__ not in __plugPresetTypes :
return None

source = __correspondingDefaultPlug( plug )

result = IECore.StringVectorData()
for n in Gaffer.Metadata.registeredValues( source ) :
for n in Gaffer.Metadata.registeredValues( plug ) :
if n.startswith( "preset:" ) :
result.append( n[7:] )

result.extend( Gaffer.Metadata.value( source, "presetNames" ) or [] )
result.extend( Gaffer.Metadata.value( plug, "presetNames" ) or [] )
return result

def __presetValuesMetadata( plug ) :

if not plug :
return None

dataType = __plugPresetTypes.get( plug.__class__ )
if dataType is None :
return None

source = __correspondingDefaultPlug( plug )

result = dataType()
for n in Gaffer.Metadata.registeredValues( source ) :
for n in Gaffer.Metadata.registeredValues( plug ) :
if n.startswith( "preset:" ) :
result.append( Gaffer.Metadata.value( source, n ) )
result.append( Gaffer.Metadata.value( plug, n ) )

result.extend( Gaffer.Metadata.value( source, "presetValues" ) or [] )
result.extend( Gaffer.Metadata.value( plug, "presetValues" ) or [] )
return result

Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "row*.*...", "presetNames", __presetNamesMetadata )
Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "row*.*...", "presetValues", __presetValuesMetadata )
def __defaultPlugPresetNamesMetadata( plug ) :

return __presetNamesMetadata( __correspondingDefaultPlug( plug ) )

def __defaultPlugPresetValuesMetadata( plug ) :

return __presetValuesMetadata( __correspondingDefaultPlug( plug ) )

def __forwardedPresetNamesMetadata( plug ) :

return __presetNamesMetadata( __presetSourcePlug( plug ) )

def __forwardedPresetValuesMetadata( plug ) :

return __presetValuesMetadata( __presetSourcePlug( plug ) )

Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "default.*...", "presetNames", __forwardedPresetNamesMetadata )
Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "default.*...", "presetValues", __forwardedPresetValuesMetadata )
Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "row*.*...", "presetNames", __defaultPlugPresetNamesMetadata )
Gaffer.Metadata.registerValue( Gaffer.Spreadsheet.RowsPlug, "row*.*...", "presetValues", __defaultPlugPresetValuesMetadata )
Loading

0 comments on commit 8653221

Please sign in to comment.