Skip to content

Commit

Permalink
fixup! ColorChooser : Maintain options state per-session
Browse files Browse the repository at this point in the history
  • Loading branch information
ericmehl committed Sep 24, 2024
1 parent db3c6d8 commit b3082aa
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 193 deletions.
9 changes: 9 additions & 0 deletions python/GafferUI/ColorChooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ def __init__( self, color=imath.Color3f( 1 ), **kw ) :
self.__visibleComponentsChangedSignal = Gaffer.Signals.Signal1()
self.__staticComponentChangedSignal = Gaffer.Signals.Signal1()
self.__colorFieldVisibleChangedSignal = Gaffer.Signals.Signal1()
self.__optionsMenuSignal = Gaffer.Signals.Signal2()

self.__updateUIFromColor()
self.__activateComponentIcons()
Expand Down Expand Up @@ -683,6 +684,13 @@ def colorFieldVisibleChangedSignal( self ) :

return self.__colorFieldVisibleChangedSignal

## A signal emitted whenever the options menu is opened.
# Slots should have the signature slot( ColorChooser, menuDefinition )
# and add menu items to `menuDefinition`.
def optionsMenuSignal( self ) :

return self.__optionsMenuSignal

## Returns True if a user would expect the specified sequence
# of changes to be merged into a single undoable event.
@classmethod
Expand Down Expand Up @@ -740,6 +748,7 @@ def __optionsMenuDefinition( self ) :
}
)

self.__optionsMenuSignal( self, result )

return result

Expand Down
113 changes: 81 additions & 32 deletions python/GafferUI/ColorChooserPlugValueWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,17 @@ def __init__( self, plugs, **kw ) :

self.__colorChooser.setSwatchesVisible( False )

options = self.__colorChooserOptions()
visibleComponents = self.__colorChooserOption( "visibleComponents" )
if visibleComponents is not None :
self.__colorChooser.setVisibleComponents( visibleComponents )

if "visibleComponents" in options :
self.__colorChooser.setVisibleComponents( options["visibleComponents"].value )
staticComponent = self.__colorChooserOption( "staticComponent" )
if staticComponent is not None :
self.__colorChooser.setColorFieldStaticComponent( staticComponent )

if "staticComponent" in options :
self.__colorChooser.setColorFieldStaticComponent( options["staticComponent"].value )

if "colorFieldVisible" in options :
self.__colorChooser.setColorFieldVisible( options["colorFieldVisible"].value )
colorFieldVisible = self.__colorChooserOption( "colorFieldVisible" )
if colorFieldVisible is not None :
self.__colorChooser.setColorFieldVisible( colorFieldVisible )

self.__colorChangedConnection = self.__colorChooser.colorChangedSignal().connect(
Gaffer.WeakMethod( self.__colorChanged )
Expand All @@ -77,6 +78,10 @@ def __init__( self, plugs, **kw ) :
self.__colorChooser.colorFieldVisibleChangedSignal().connect(
functools.partial( Gaffer.WeakMethod( self.__colorChooserColorFieldVisibleChanged ) )
)
self.__colorChooser.optionsMenuSignal().connect(
functools.partial( Gaffer.WeakMethod( self.__colorChooserOptionsMenu ) ),
scoped = False
)

self.__lastChangedReason = None
self.__mergeGroupId = 0
Expand Down Expand Up @@ -114,45 +119,43 @@ def __colorChanged( self, colorChooser, reason ) :
for plug in self.getPlugs() :
plug.setValue( self.__colorChooser.getColor() )

def __colorChooserOptionChanged( self, value, key ) :

if Gaffer.Metadata.value( "colorChooser:inlineOptions", "userDefault" ) is None :
sessionOptions = Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" )
if sessionOptions is None :
sessionOptions = IECore.CompoundData()
Gaffer.Metadata.registerValue( "colorChooser:inlineOptions", "sessionDefault", sessionOptions )

sessionOptions.update( { key: value } )
def __colorChooserOptionChanged( self, keySuffix, value ) :

for p in self.getPlugs() :
plugOptions = Gaffer.Metadata.value( p, "colorChooser:inlineOptions" )
if plugOptions is None :
plugOptions = IECore.CompoundData()
Gaffer.Metadata.registerValue( p, "colorChooser:inlineOptions", plugOptions, persistent = False )
Gaffer.Metadata.deregisterValue( p, "colorChooser:inline:" + keySuffix )
Gaffer.Metadata.registerValue( p, "colorChooser:inline:" + keySuffix, value, persistent = False )

def __colorChooserOption( self, keySuffix ) :

plugOptions.update( { key: value } )
return sole( Gaffer.Metadata.value( p, "colorChooser:inline:" + keySuffix ) for p in self.getPlugs() )

def __colorChooserVisibleComponentsChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getVisibleComponents(), "visibleComponents" )
self.__colorChooserOptionChanged( "visibleComponents", colorChooser.getVisibleComponents() )

def __colorChooserStaticComponentChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getColorFieldStaticComponent(), "staticComponent" )
self.__colorChooserOptionChanged( "staticComponent", colorChooser.getColorFieldStaticComponent() )

def __colorChooserColorFieldVisibleChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getColorFieldVisible(), "colorFieldVisible" )
self.__colorChooserOptionChanged( "colorFieldVisible", colorChooser.getColorFieldVisible() )

def __colorChooserOptions( self ) :
def __colorChooserOptionsMenu( self, colorChooser, menuDefinition ) :

v = sole( Gaffer.Metadata.value( p, "colorChooser:inlineOptions" ) for p in self.getPlugs() )
if v is None :
v = Gaffer.Metadata.value( "colorChooser:inlineOptions", "userDefault" )
if v is None :
v = Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) or IECore.CompoundData()
menuDefinition.append( "/__saveDefaultOptions__", { "divider": True, "label": "Defaults" } )

return v
menuDefinition.append(
"/Save Inline Defaults",
{
"command": functools.partial(
saveDefaultOptions,
colorChooser,
"colorChooser:inline:",
self.ancestor( GafferUI.ScriptWindow ).scriptNode().applicationRoot().preferencesLocation() / "__colorChooser.py"
),
}
)

def __allComponentsEditable( self ) :

Expand All @@ -168,3 +171,49 @@ def __allComponentsEditable( self ) :
return False

return True

def saveDefaultOptions( colorChooser, keyPrefix, scriptPath = None ) :

for k in [ "visibleComponents", "staticComponent", "colorFieldVisible" ] :
Gaffer.Metadata.deregisterValue( Gaffer.Color3fPlug, keyPrefix + k )
Gaffer.Metadata.deregisterValue( Gaffer.Color4fPlug, keyPrefix + k )

visibleComponents = colorChooser.getVisibleComponents()
Gaffer.Metadata.registerValue( Gaffer.Color3fPlug, keyPrefix + "visibleComponents", visibleComponents )
Gaffer.Metadata.registerValue( Gaffer.Color4fPlug, keyPrefix + "visibleComponents", visibleComponents )

staticComponent = colorChooser.getColorFieldStaticComponent()
Gaffer.Metadata.registerValue( Gaffer.Color3fPlug, keyPrefix + "staticComponent", staticComponent )
Gaffer.Metadata.registerValue( Gaffer.Color4fPlug, keyPrefix + "staticComponent", staticComponent )

colorFieldVisible = colorChooser.getColorFieldVisible()
Gaffer.Metadata.registerValue( Gaffer.Color3fPlug, keyPrefix + "colorFieldVisible", colorFieldVisible )
Gaffer.Metadata.registerValue( Gaffer.Color4fPlug, keyPrefix + "colorFieldVisible", colorFieldVisible )

if scriptPath is None :
return

if scriptPath.is_dir() :
raise RuntimeError( f"Cannot write Color Chooser default options script \"{scriptPath}\", a directory at that path exists.")

if scriptPath.exists() :
with open( scriptPath, "r" ) as inFile :
script = inFile.readlines()
else :
script = [
"# This file was automatically generated by Gaffer.\n",
"# Do not edit this file - it will be overwritten.\n",
"\n",
"import Gaffer\n",
"\n"
]

newScript = [l for l in script if keyPrefix not in l]

for c in [ "3", "4" ] :
newScript.append( f"Gaffer.Metadata.registerValue( Gaffer.Color{c}fPlug, \"{keyPrefix}visibleComponents\", \"{visibleComponents}\" )\n" )
newScript.append( f"Gaffer.Metadata.registerValue( Gaffer.Color{c}fPlug, \"{keyPrefix}staticComponent\", \"{staticComponent}\" )\n" )
newScript.append( f"Gaffer.Metadata.registerValue( Gaffer.Color{c}fPlug, \"{keyPrefix}colorFieldVisible\", {colorFieldVisible} )\n" )

with open( scriptPath, "w" ) as outFile :
outFile.writelines( newScript )
74 changes: 39 additions & 35 deletions python/GafferUI/ColorSwatchPlugValueWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import Gaffer
import GafferUI
from GafferUI.PlugValueWidget import sole
from GafferUI.ColorChooserPlugValueWidget import saveDefaultOptions

class ColorSwatchPlugValueWidget( GafferUI.PlugValueWidget ) :

Expand Down Expand Up @@ -146,6 +147,10 @@ def __init__( self, plugs, parentWindow ) :
self.colorChooser().colorFieldVisibleChangedSignal().connect(
functools.partial( Gaffer.WeakMethod( self.__colorChooserColorFieldVisibleChanged ) )
)
self.colorChooser().optionsMenuSignal().connect(
functools.partial( Gaffer.WeakMethod( self.__colorChooserOptionsMenu ) ),
scoped = False
)

self.confirmButton.clickedSignal().connect( Gaffer.WeakMethod( self.__buttonClicked ) )
self.cancelButton.clickedSignal().connect( Gaffer.WeakMethod( self.__buttonClicked ) )
Expand All @@ -166,16 +171,17 @@ def __init__( self, plugs, parentWindow ) :

self.__plugSet( plug )

options = self.__colorChooserOptions()

if "visibleComponents" in options :
self.colorChooser().setVisibleComponents( options["visibleComponents"].value )
visibleComponents = self.__colorChooserOption( "visibleComponents" )
if visibleComponents is not None :
self.colorChooser().setVisibleComponents( visibleComponents )

if "staticComponent" in options :
self.colorChooser().setColorFieldStaticComponent( options["staticComponent"].value )
staticComponent = self.__colorChooserOption( "staticComponent" )
if staticComponent is not None :
self.colorChooser().setColorFieldStaticComponent( staticComponent )

if "colorFieldVisible" in options :
self.colorChooser().setColorFieldVisible( options["colorFieldVisible"].value )
colorFieldVisible = self.__colorChooserOption( "colorFieldVisible" )
if colorFieldVisible is not None :
self.colorChooser().setColorFieldVisible( colorFieldVisible )

parentWindow.addChildWindow( self, removeOnClose = True )

Expand Down Expand Up @@ -237,49 +243,47 @@ def __buttonClicked( self, button ) :
assert( not self.visible() )
GafferUI.WidgetAlgo.keepUntilIdle( self )

def __colorChooserOptionsMenu( self, colorChooser, menuDefinition ) :

menuDefinition.append( "/__saveDefaultOptions__", { "divider": True, "label": "Defaults" } )

menuDefinition.append(
"/Save Dialogue Defaults",
{
"command": functools.partial(
saveDefaultOptions,
colorChooser,
"colorChooser:dialogue:",
self.ancestor( GafferUI.ScriptWindow ).scriptNode().applicationRoot().preferencesLocation() / "__colorChooser.py"
)
}
)

def __destroy( self, *unused ) :

self.parent().removeChild( self )

# \todo Extract these two methods to share with `ColorChooserPlugValueWidget` which has
# an almost identical implementation.

def __colorChooserOptionChanged( self, value, key ) :

if Gaffer.Metadata.value( "colorChooser:dialogueOptions", "userDefault" ) is None :
sessionOptions = Gaffer.Metadata.value( "colorChooser:dialogueOptions", "sessionDefault" )
if sessionOptions is None :
sessionOptions = IECore.CompoundData()
Gaffer.Metadata.registerValue( "colorChooser:dialogueOptions", "sessionDefault", sessionOptions )

sessionOptions.update( { key: value } )
def __colorChooserOptionChanged( self, keySuffix, value ) :

for p in self.__plugs :
plugOptions = Gaffer.Metadata.value( p, "colorChooser:dialogueOptions" )
if plugOptions is None :
plugOptions = IECore.CompoundData()
Gaffer.Metadata.registerValue( p, "colorChooser:dialogueOptions", plugOptions, persistent = False )
Gaffer.Metadata.deregisterValue( p, "colorChooser:dialogue:" + keySuffix )
Gaffer.Metadata.registerValue( p, "colorChooser:dialogue:" + keySuffix, value, persistent = False )

def __colorChooserOption( self, keySuffix ) :

plugOptions.update( { key: value } )
return sole( Gaffer.Metadata.value( p, "colorChooser:dialogue:" + keySuffix ) for p in self.__plugs )

def __colorChooserVisibleComponentsChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getVisibleComponents(), "visibleComponents" )
self.__colorChooserOptionChanged( "visibleComponents", colorChooser.getVisibleComponents() )

def __colorChooserStaticComponentChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getColorFieldStaticComponent(), "staticComponent" )
self.__colorChooserOptionChanged( "staticComponent", colorChooser.getColorFieldStaticComponent() )

def __colorChooserColorFieldVisibleChanged( self, colorChooser ) :

self.__colorChooserOptionChanged( colorChooser.getColorFieldVisible(), "colorFieldVisible" )

def __colorChooserOptions( self ) :

v = sole( Gaffer.Metadata.value( p, "colorChooser:dialogueOptions" ) for p in self.__plugs )
if v is None :
v = Gaffer.Metadata.value( "colorChooser:dialogueOptions", "userDefault" )
if v is None :
v = Gaffer.Metadata.value( "colorChooser:dialogueOptions", "sessionDefault" ) or IECore.CompoundData()

return v
self.__colorChooserOptionChanged( "colorFieldVisible", colorChooser.getColorFieldVisible() )
Loading

0 comments on commit b3082aa

Please sign in to comment.