From f3c8804689355544f7e11f0b06b229a32543e891 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Wed, 14 Aug 2024 12:43:09 -0400 Subject: [PATCH] ColorChooser : Maintain options state per-session --- Changes.md | 6 +- python/GafferUI/ColorChooser.py | 112 ++++++++- .../GafferUI/ColorChooserPlugValueWidget.py | 65 ++++++ python/GafferUI/ColorSwatchPlugValueWidget.py | 69 ++++++ python/GafferUITest/ColorChooserTest.py | 218 ++++++++++++++++++ 5 files changed, 457 insertions(+), 13 deletions(-) diff --git a/Changes.md b/Changes.md index 52999983bc3..44d91d7584b 100644 --- a/Changes.md +++ b/Changes.md @@ -7,7 +7,11 @@ Features - ColorChooser : - Add sliders for TMI (temperature, magenta, intensity) color space. - Add color field, a widget giving control of two channels of "RGB", "HSV" or "TMI" triplets. The third channel is held constant. - - The color field, HSV slider group and TMI slider group can be toggled on or off. + - The color field, HSV slider group and TMI slider group can be toggled on or off. Visibility of the elements is maintained for the duration of the Gaffer session. + - Default visibility of the UI elements can be set at startup by setting `colorChooser:inlineOptions` and `colorChooser:dialogueOptions` `userData` entries for the inline chooser and dialogue chooser respectively. The value of the metadata entry is an `IECore.CompoundData` object with the following optional keys : + - `visibleComponents` : A string where each character is a visible component slider. Optional components are `rgbahsvtmi`. + - `staticComponent` : A single character string for the component to use as the static component for the color field. + - `colorFieldVisible` : A boolean indicating if the color field should be visible or not. 1.4.11.0 (relative to 1.4.10.0) ======== diff --git a/python/GafferUI/ColorChooser.py b/python/GafferUI/ColorChooser.py index fac8411f5e6..10dfac2f2be 100644 --- a/python/GafferUI/ColorChooser.py +++ b/python/GafferUI/ColorChooser.py @@ -514,7 +514,7 @@ def __init__( self, color=imath.Color3f( 1 ), **kw ) : self.__channelLabels[component]._qtWidget().setProperty( "gafferColorStaticComponent", True) self.__channelLabels[component].buttonPressSignal().connect( functools.partial( - Gaffer.WeakMethod( self.__setStaticComponent ), + Gaffer.WeakMethod( self.__channelLabelPressed ), component = component ), scoped = False @@ -572,6 +572,9 @@ def __init__( self, color=imath.Color3f( 1 ), **kw ) : self.__colorSwatch._qtWidget().setFixedHeight( 40 ) self.__colorChangedSignal = Gaffer.Signals.Signal2() + self.__visibleComponentsChangedSignal = Gaffer.Signals.Signal2() + self.__staticComponentChangedSignal = Gaffer.Signals.Signal2() + self.__colorFieldVisibleChangedSignal = Gaffer.Signals.Signal2() self.__updateUIFromColor() self.__activateComponentIcons() @@ -611,6 +614,31 @@ def setErrored( self, errored ) : def getErrored( self ) : return any( w.getErrored() for w in self.__numericWidgets.values() ) + def setVisibleComponents( self, components ) : + + self.__setVisibleComponentsInternal( components ) + + def getVisibleComponents( self ) : + + return "".join( [ k for k, v in self.__sliders.items() if v.getVisible() ] ) + + def setStaticComponent( self, component ) : + + self.__setStaticComponentInternal( component ) + + def getStaticComponent( self ) : + + c, staticComponent = self.__colorField.getColor() + return staticComponent + + def setColorFieldVisible( self, visible ) : + + self.__setColorFieldVisibleInternal( visible ) + + def getColorFieldVisible( self ) : + + return self.__colorField.getVisible() + ## A signal emitted whenever the color is changed. Slots should # have the signature slot( ColorChooser, reason ). The reason # argument may be passed either a ColorChooser.ColorChangedReason, @@ -620,6 +648,29 @@ def colorChangedSignal( self ) : return self.__colorChangedSignal + ## A signal emitted whenver the visible components are changed. Slots + # should have the signature slot( ColorChooser, visibleComponents ). + # `visibleComponents` is a string representing the components currently + # visible. + def visibleComponentsChangedSignal( self ) : + + return self.__visibleComponentsChangedSignal + + ## A signal emitted whenver the static component is changed. Slots + # should have the signature slot( ColorChooser, staticComponent ). + # `staticComponent` is a single character string representing the + # current static component. + def staticComponentChangedSignal( self ) : + + return self.__staticComponentChangedSignal + + ## A signal emitted whenever the visibility of the color field changes. + # Slots should have the signature slot( ColorChooser, visible ). + # `visible` is a boolean representing the current visibility. + def colorFieldVisibleChangedSignal( self ) : + + return self.__colorFieldVisibleChangedSignal + ## Returns True if a user would expect the specified sequence # of changes to be merged into a single undoable event. @classmethod @@ -681,22 +732,29 @@ def __optionsMenuDefinition( self ) : return result + def __channelLabelPressed( self, widget, event, component ) : + + if event.buttons != GafferUI.ButtonEvent.Buttons.Left : + return False + + self.__setStaticComponentInternal( component ) + + return True + def __toggleComponentTriplet( self, channels, *unused ) : + visibleComponents = set( self.getVisibleComponents() ) for c in channels : - self.__channelLabels[c].setVisible( not self.__channelLabels[c].getVisible() ) - self.__numericWidgets[c].setVisible( not self.__numericWidgets[c].getVisible() ) - self.__sliders[c].setVisible( not self.__sliders[c].getVisible() ) + if c in visibleComponents : + visibleComponents.remove( c ) + else : + visibleComponents.add( c ) + + self.__setVisibleComponentsInternal( "".join( visibleComponents ) ) def __toggleColorField( self, *unused ) : - visible = not self.__colorField.getVisible() - self.__colorField.setVisible( visible ) - - if visible : - self.__activateComponentIcons() - else : - self.__clearComponentIcons() + self.__setColorFieldVisibleInternal( not self.__colorField.getVisible() ) def __initialColorPress( self, button, event ) : @@ -939,4 +997,34 @@ def __setStaticComponentInternal( self, component ) : self.__colorField.setColor( self.__colorTMI, component ) if self.__colorField.getVisible() : - self.__activateComponentIcons() \ No newline at end of file + self.__activateComponentIcons() + + self.__staticComponentChangedSignal( self, component ) + + def __setVisibleComponentsInternal( self, components ) : + + componentsSet = set( components ) + if componentsSet == set( self.getVisibleComponents() ) : + return + + for c in self.__sliders.keys() : + visible = c in componentsSet + self.__channelLabels[c].setVisible( visible ) + self.__numericWidgets[c].setVisible( visible ) + self.__sliders[c].setVisible( visible ) + + self.__visibleComponentsChangedSignal( self, components ) + + def __setColorFieldVisibleInternal( self, visible ) : + + if visible == self.__colorField.getVisible() : + return + + self.__colorField.setVisible( visible ) + + if visible : + self.__activateComponentIcons() + else : + self.__clearComponentIcons() + + self.__colorFieldVisibleChangedSignal( self, visible ) diff --git a/python/GafferUI/ColorChooserPlugValueWidget.py b/python/GafferUI/ColorChooserPlugValueWidget.py index d6164b11d5d..30dfbe73c41 100644 --- a/python/GafferUI/ColorChooserPlugValueWidget.py +++ b/python/GafferUI/ColorChooserPlugValueWidget.py @@ -34,10 +34,14 @@ # ########################################################################## +import functools import imath +import IECore + import Gaffer import GafferUI +from GafferUI.PlugValueWidget import sole class ColorChooserPlugValueWidget( GafferUI.PlugValueWidget ) : @@ -49,10 +53,43 @@ def __init__( self, plugs, **kw ) : self.__colorChooser.setSwatchesVisible( False ) + options = self.__colorChooserOptions() + + if "visibleComponents" in options : + self.__colorChooser.setVisibleComponents( options["visibleComponents"].value ) + + if "staticComponent" in options : + self.__colorChooser.setStaticComponent( options["staticComponent"].value ) + + if "colorFieldVisible" in options : + self.__colorChooser.setColorFieldVisible( options["colorFieldVisible"].value ) + self.__colorChangedConnection = self.__colorChooser.colorChangedSignal().connect( Gaffer.WeakMethod( self.__colorChanged ), scoped = False ) + self.__colorChooser.visibleComponentsChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "visibleComponents" + ), + scoped = False + ) + self.__colorChooser.staticComponentChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "staticComponent" + ), + scoped = False + ) + self.__colorChooser.colorFieldVisibleChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "colorFieldVisible" + ), + scoped = False + ) + self.__lastChangedReason = None self.__mergeGroupId = 0 @@ -89,6 +126,34 @@ def __colorChanged( self, colorChooser, reason ) : for plug in self.getPlugs() : plug.setValue( self.__colorChooser.getColor() ) + def __colorChooserOptionChanged( self, colorChooser, 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 } ) + + 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 ) + + plugOptions.update( { key: value } ) + + def __colorChooserOptions( self ) : + + 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() + + return v + def __allComponentsEditable( self ) : if not self._editable() : diff --git a/python/GafferUI/ColorSwatchPlugValueWidget.py b/python/GafferUI/ColorSwatchPlugValueWidget.py index 23ffce27f6f..b0cf145969d 100644 --- a/python/GafferUI/ColorSwatchPlugValueWidget.py +++ b/python/GafferUI/ColorSwatchPlugValueWidget.py @@ -37,9 +37,13 @@ import weakref import imath +import functools + +import IECore import Gaffer import GafferUI +from GafferUI.PlugValueWidget import sole class ColorSwatchPlugValueWidget( GafferUI.PlugValueWidget ) : @@ -132,6 +136,29 @@ def __init__( self, plugs, parentWindow ) : self.__mergeGroupId = 0 self.__colorChangedConnection = self.colorChooser().colorChangedSignal().connect( Gaffer.WeakMethod( self.__colorChanged ), scoped = False ) + + self.colorChooser().visibleComponentsChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "visibleComponents" + ), + scoped = False + ) + self.colorChooser().staticComponentChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "staticComponent" + ), + scoped = False + ) + self.colorChooser().colorFieldVisibleChangedSignal().connect( + functools.partial( + Gaffer.WeakMethod( self.__colorChooserOptionChanged ), + key = "colorFieldVisible" + ), + scoped = False + ) + self.confirmButton.clickedSignal().connect( Gaffer.WeakMethod( self.__buttonClicked ), scoped = False ) self.cancelButton.clickedSignal().connect( Gaffer.WeakMethod( self.__buttonClicked ), scoped = False ) @@ -151,6 +178,17 @@ def __init__( self, plugs, parentWindow ) : self.__plugSet( plug ) + options = self.__colorChooserOptions() + + if "visibleComponents" in options : + self.colorChooser().setVisibleComponents( options["visibleComponents"].value ) + + if "staticComponent" in options : + self.colorChooser().setStaticComponent( options["staticComponent"].value ) + + if "colorFieldVisible" in options : + self.colorChooser().setColorFieldVisible( options["colorFieldVisible"].value ) + parentWindow.addChildWindow( self, removeOnClose = True ) @classmethod @@ -214,3 +252,34 @@ def __buttonClicked( self, button ) : 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, colorChooser, 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 } ) + + 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 ) + + plugOptions.update( { key: value } ) + + 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 diff --git a/python/GafferUITest/ColorChooserTest.py b/python/GafferUITest/ColorChooserTest.py index dc333fd2e37..ed8f638bc48 100644 --- a/python/GafferUITest/ColorChooserTest.py +++ b/python/GafferUITest/ColorChooserTest.py @@ -40,6 +40,10 @@ import imath import OpenImageIO +import IECore + +import Gaffer +import GafferUI from GafferUI.ColorChooser import _tmiToRGB from GafferUI.ColorChooser import _rgbToTMI import GafferUITest @@ -84,6 +88,220 @@ def testTMIAlpha( self ) : rgbConverted = _tmiToRGB( tmi ) self.assertEqual( rgbConverted.a, rgb.a ) + def __colorChooserFromWidget( self, widget ) : + + return widget._ColorPlugValueWidget__colorChooser._ColorChooserPlugValueWidget__colorChooser + + def __sliderFromWidget( self, widget, component ) : + + c = self.__colorChooserFromWidget( widget ) + return c._ColorChooser__sliders[component] + + def __setVisibleComponents( self, widget, channels ) : + + c = self.__colorChooserFromWidget( widget ) + c.setVisibleComponents( channels ) + + def __setStaticComponent( self, widget, component ) : + + c = self.__colorChooserFromWidget( widget ) + c.setStaticComponent( component ) + + def __getStaticComponent( self, widget ) : + + c = self.__colorChooserFromWidget( widget ) + return c.getStaticComponent() + + def __setColorFieldVisibility( self, widget, visible ) : + + c = self.__colorChooserFromWidget( widget ) + c.setColorFieldVisible( visible ) + + def __getColorFieldVisibility( self, widget ) : + + c = self.__colorChooserFromWidget( widget ) + return c.getColorFieldVisible() + + def testMetadata( self ) : + + script = Gaffer.ScriptNode() + + script["node"] = Gaffer.Node() + script["node"]["rgbPlug1"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["node"]["rgbPlug2"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + + widget1 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug1"] ) + + # Default state + + for c in "rgbhsvtmi" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertIsNone( Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) ) + for p in [ "rgbPlug1", "rgbPlug2" ] : + self.assertIsNone( Gaffer.Metadata.value( script["node"][p], "colorChooser:inlineOptions" ) ) + self.assertEqual( self.__getStaticComponent( widget1 ), "h" ) + self.assertTrue( self.__getColorFieldVisibility( widget1 ) ) + + # Modify widget1 + + self.__setVisibleComponents( widget1, "rgbtmi" ) + self.__setStaticComponent( widget1, "t" ) + self.__setColorFieldVisibility( widget1, False ) + + for c in "rgbtmi" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + for c in "hsv" : + self.assertFalse( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "t" ) + self.assertFalse( self.__getColorFieldVisibility( widget1 ) ) + + sessionOptions = Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) + plug1Options = Gaffer.Metadata.value( script["node"]["rgbPlug1"], "colorChooser:inlineOptions" ) + self.assertEqual( set( sessionOptions["visibleComponents"].value ), set( "rgbtmi" ) ) + self.assertEqual( set( plug1Options["visibleComponents"].value ), set( "rgbtmi" ) ) + self.assertEqual( sessionOptions["staticComponent"].value, "t" ) + self.assertEqual( plug1Options["staticComponent"].value, "t" ) + self.assertFalse( sessionOptions["colorFieldVisible"].value ) + self.assertFalse( plug1Options["colorFieldVisible"].value ) + + # Recreate widget1 and should have the same state + del widget1 + widget1 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug1"] ) + + for c in "rgbtmi" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + for c in "hsv" : + self.assertFalse( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "t" ) + self.assertFalse( self.__getColorFieldVisibility( widget1 ) ) + + # A widget for a second plug should adopt the same state as widget1 + + widget2 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug2"] ) + + for c in "rgbtmi" : + self.assertTrue( self.__sliderFromWidget( widget2, c ).getVisible() ) + for c in "hsv" : + self.assertFalse( self.__sliderFromWidget( widget2, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget2 ), "t" ) + self.assertFalse( self.__getColorFieldVisibility( widget2 ) ) + + # Changing widget2 should not affect widget1, but should change `sessionDefault` + self.__setVisibleComponents( widget2, "rgb" ) + self.__setStaticComponent( widget2, "r" ) + self.__setColorFieldVisibility( widget2, True ) + + for c in "rgbtmi" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + for c in "hsv" : + self.assertFalse( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "t" ) + self.assertFalse( self.__getColorFieldVisibility( widget1 ) ) + + for c in "rgb" : + self.assertTrue( self.__sliderFromWidget( widget2, c ).getVisible() ) + for c in "hsvtmi" : + self.assertFalse( self.__sliderFromWidget( widget2, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget2 ), "r" ) + self.assertTrue( self.__getColorFieldVisibility( widget2 ) ) + + sessionOptions = Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) + plug1Options = Gaffer.Metadata.value( script["node"]["rgbPlug1"], "colorChooser:inlineOptions" ) + plug2Options = Gaffer.Metadata.value( script["node"]["rgbPlug2"], "colorChooser:inlineOptions" ) + + self.assertEqual( set( plug1Options["visibleComponents"].value ), set( "rgbtmi" ) ) + self.assertEqual( set( plug2Options["visibleComponents"].value ), set( "rgb" ) ) + self.assertEqual( set( sessionOptions["visibleComponents"].value ), set( "rgb" ) ) + self.assertEqual( plug1Options["staticComponent"].value, "t" ) + self.assertEqual( plug2Options["staticComponent"].value, "r" ) + self.assertEqual( sessionOptions["staticComponent"].value, "r" ) + self.assertFalse( plug1Options["colorFieldVisible"].value ) + self.assertTrue( plug2Options["colorFieldVisible"].value ) + self.assertTrue( sessionOptions["colorFieldVisible"].value ) + + # Don't serialize state + del widget1 + del widget2 + Gaffer.Metadata.deregisterValue( "colorChooser:inlineOptions", "sessionDefault" ) + + script2 = Gaffer.ScriptNode() + script2.execute( script.serialise() ) + + widget1 = GafferUI.ColorPlugValueWidget( script2["node"]["rgbPlug1"] ) + widget2 = GafferUI.ColorPlugValueWidget( script2["node"]["rgbPlug2"] ) + + for c in "rgbhsvtmi" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertTrue( self.__sliderFromWidget( widget2, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "h" ) + self.assertEqual( self.__getStaticComponent( widget2 ), "h" ) + self.assertIsNone( Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) ) + for p in [ "rgbPlug1", "rgbPlug2" ] : + self.assertIsNone( Gaffer.Metadata.value( script2["node"][p], "colorChooser:inlineOptions" ) ) + + def testUserDefaultMetadata( self ) : + + # Set `userDefault` + Gaffer.Metadata.registerValue( + "colorChooser:inlineOptions", + "userDefault", + { + "visibleComponents": "rgb", + "staticComponent": "r", + "colorFieldVisible": False + } + ) + + script = Gaffer.ScriptNode() + + script["node"] = Gaffer.Node() + script["node"]["rgbPlug1"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["node"]["rgbPlug2"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + + widget1 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug1"] ) + + # Should get `userDefault` values + for c in "rgb" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + for c in "hsvtmi" : + self.assertFalse( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "r" ) + self.assertFalse( self.__getColorFieldVisibility( widget1 ) ) + + self.assertIsNone( Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) ) + for p in [ "rgbPlug1", "rgbPlug2" ] : + self.assertIsNone( Gaffer.Metadata.value( script["node"][p], "colorChooser:inlineOptions" ) ) + + # Change widget1 and recreate it + self.__setVisibleComponents( widget1, "rgbhsv" ) + self.__setStaticComponent( widget1, "g" ) + self.__setColorFieldVisibility( widget1, True ) + + del widget1 + + widget1 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug1"] ) + + # Should have HSV, static component G, visible color field + for c in "rgbhsv" : + self.assertTrue( self.__sliderFromWidget( widget1, c ).getVisible() ) + for c in "tmi" : + self.assertFalse( self.__sliderFromWidget( widget1, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget1 ), "g" ) + self.assertTrue( self.__getColorFieldVisibility( widget1 ) ) + + # A new widget, without any per-plug metadata should get `userDefault` + + widget2 = GafferUI.ColorPlugValueWidget( script["node"]["rgbPlug2"] ) + + for c in "rgb" : + self.assertTrue( self.__sliderFromWidget( widget2, c ).getVisible() ) + for c in "hsvtmi" : + self.assertFalse( self.__sliderFromWidget( widget2, c ).getVisible() ) + self.assertEqual( self.__getStaticComponent( widget2 ), "r" ) + self.assertFalse( self.__getColorFieldVisibility( widget2 ) ) + + self.assertIsNone( Gaffer.Metadata.value( "colorChooser:inlineOptions", "sessionDefault" ) ) + if __name__ == "__main__" : unittest.main() \ No newline at end of file