Skip to content

Commit

Permalink
Merge branch '1.4_maintenance'
Browse files Browse the repository at this point in the history
  • Loading branch information
murraystevenson committed Jul 19, 2024
2 parents 79970a7 + 58afc72 commit 0831b50
Show file tree
Hide file tree
Showing 24 changed files with 484 additions and 128 deletions.
12 changes: 12 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,16 @@ Breaking Changes
1.4.x.x (relative to 1.4.9.0)
=======

Improvements
------------

- LightEditor : Values of inherited attributes are now displayed in the Light Editor. These are presented as dimmed "fallback" values.
- LightEditor, RenderPassEditor : Fallback values shown in the history window are displayed with the same dimmed text colour used for fallback values in editor columns.

Fixes
-----

- LightEditor, RenderPassEditor : Added missing icon representing use of the `CreateIfMissing` tweak mode in the history window.

1.4.9.0 (relative to 1.4.8.0)
=======
Expand Down Expand Up @@ -709,7 +718,10 @@ Build
1.3.16.x (relative to 1.3.16.6)
========

Fixes
-----

- LightEditor, RenderPassEditor : Added missing icon representing use of the `CreateIfMissing` tweak mode in the history window.

1.3.16.6 (relative to 1.3.16.5)
========
Expand Down
2 changes: 1 addition & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ libraries = {

"GafferUITest" : {

"additionalFiles" : glob.glob( "python/GafferUITest/scripts/*.gfr" ),
"additionalFiles" : glob.glob( "python/GafferUITest/scripts/*.gfr" ) + glob.glob( "python/GafferUITest/images/*" ),

},

Expand Down
1 change: 1 addition & 0 deletions include/GafferSceneUI/Private/AttributeInspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class GAFFERSCENEUI_API AttributeInspector : public Inspector
IECore::ConstObjectPtr value( const GafferScene::SceneAlgo::History *history) const override;
Gaffer::ValuePlugPtr source( const GafferScene::SceneAlgo::History *history, std::string &editWarning ) const override;
EditFunctionOrFailure editFunction( Gaffer::EditScope *scope, const GafferScene::SceneAlgo::History *history) const override;
IECore::ConstObjectPtr fallbackValue( const GafferScene::SceneAlgo::History *history ) const override;

bool attributeExists() const;

Expand Down
6 changes: 3 additions & 3 deletions include/GafferSceneUI/Private/Inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ class GAFFERSCENEUI_API Inspector : public IECore::RefCounted, public Gaffer::Si

/// Returns a `Path` representing the history for the inspected property
/// in the current context. The path has a child for each predecessor in
/// the history, and properties `history:value`, `history:operation`,
/// `history:source`, `history:editWarning` and `history:node`.
/// the history, and properties `history:value`, `history:fallbackValue`,
/// `history:operation`, `history:source`, `history:editWarning` and `history:node`.
Gaffer::PathPtr historyPath();

protected :
Expand Down Expand Up @@ -179,7 +179,7 @@ class GAFFERSCENEUI_API Inspector : public IECore::RefCounted, public Gaffer::Si

/// Can be implemented by derived classes to provide a fallback value for the inspection,
/// used when no value is returned from `value()`.
virtual IECore::ConstObjectPtr fallbackValue() const;
virtual IECore::ConstObjectPtr fallbackValue( const GafferScene::SceneAlgo::History *history ) const;

protected :

Expand Down
2 changes: 1 addition & 1 deletion include/GafferSceneUI/Private/OptionInspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class GAFFERSCENEUI_API OptionInspector : public Inspector
IECore::ConstObjectPtr value( const GafferScene::SceneAlgo::History *history ) const override;
Gaffer::ValuePlugPtr source( const GafferScene::SceneAlgo::History *history, std::string &editWarning ) const override;
EditFunctionOrFailure editFunction( Gaffer::EditScope *scope, const GafferScene::SceneAlgo::History *history ) const override;
IECore::ConstObjectPtr fallbackValue() const override;
IECore::ConstObjectPtr fallbackValue( const GafferScene::SceneAlgo::History *history ) const override;

private :

Expand Down
1 change: 1 addition & 0 deletions include/GafferSceneUI/Private/ParameterInspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class GAFFERSCENEUI_API ParameterInspector : public AttributeInspector
IECore::ConstObjectPtr value( const GafferScene::SceneAlgo::History *history ) const override;
Gaffer::ValuePlugPtr source( const GafferScene::SceneAlgo::History *history, std::string &editWarning ) const override;
EditFunctionOrFailure editFunction( Gaffer::EditScope *editScope, const GafferScene::SceneAlgo::History *history ) const override;
IECore::ConstObjectPtr fallbackValue( const GafferScene::SceneAlgo::History *history ) const override;

const IECoreScene::ShaderNetwork::Parameter m_parameter;

Expand Down
1 change: 1 addition & 0 deletions include/GafferSceneUI/Private/SetMembershipInspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class GAFFERSCENEUI_API SetMembershipInspector : public Inspector
/// those are found.
Gaffer::ValuePlugPtr source( const GafferScene::SceneAlgo::History *history, std::string &editWarning ) const override;
EditFunctionOrFailure editFunction( Gaffer::EditScope *scope, const GafferScene::SceneAlgo::History *history ) const override;
IECore::ConstObjectPtr fallbackValue( const GafferScene::SceneAlgo::History *history ) const override;

private :

Expand Down
21 changes: 1 addition & 20 deletions python/GafferSceneUI/LightEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,26 +407,7 @@ def __toggleBoolean( self, inspectors, inspections ) :
# First we need to find out what the new value would be for each plug in isolation.
for inspector, pathInspections in inspectors.items() :
for path, inspection in pathInspections.items() :
currentValue = inspection.value().value if inspection.value() is not None else None

if isinstance( inspector, GafferSceneUI.Private.AttributeInspector ) :
fullAttributes = self.settings()["in"].fullAttributes( path[:-1] )
parentValueData = fullAttributes.get( inspector.name(), None )
parentValue = parentValueData.value if parentValueData is not None else False

currentValues.append( currentValue if currentValue is not None else parentValue )
elif isinstance( inspector, GafferSceneUI.Private.SetMembershipInspector ) :
if currentValue is not None :
currentValues.append(
True if currentValue & (
IECore.PathMatcher.Result.ExactMatch |
IECore.PathMatcher.Result.AncestorMatch
) else False
)
else :
currentValues.append( False )
else :
currentValues.append( currentValue )
currentValues.append( inspection.value().value if inspection.value() is not None else False )

# Now set the value for all plugs, defaulting to `True` if they are not
# currently all the same.
Expand Down
27 changes: 16 additions & 11 deletions python/GafferSceneUI/_HistoryWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#
##########################################################################

import IECore
import imath

import Gaffer
import GafferUI
Expand Down Expand Up @@ -63,6 +63,7 @@ def cellData( self, path, canceller = None ) :
Gaffer.TweakPlug.Mode.Multiply : "multiplySmall.png",
Gaffer.TweakPlug.Mode.Remove : "removeSmall.png",
Gaffer.TweakPlug.Mode.Create : "createSmall.png",
Gaffer.TweakPlug.Mode.CreateIfMissing : "createIfMissingSmall.png",
Gaffer.TweakPlug.Mode.Min : "lessThanSmall.png",
Gaffer.TweakPlug.Mode.Max : "greaterThanSmall.png",
Gaffer.TweakPlug.Mode.ListAppend : "listAppendSmall.png",
Expand Down Expand Up @@ -98,28 +99,34 @@ def headerData( self, canceller = None ) :

return self.CellData( self.__title )

# \todo This duplicates logic from (in this case) `_GafferSceneUI._LightEditorSetMembershipColumn`.
# \todo This duplicates logic from (in this case) `_GafferSceneUI._LightEditorInspectorColumn`.
# Refactor to allow calling `_GafferSceneUI.InspectorColumn.cellData()` from `_HistoryWindow` to
# remove this duplication for columns that customize their value presentation.
class _SetMembershipColumn( GafferUI.PathColumn ) :
class _ValueColumn( GafferUI.PathColumn ) :

def __init__( self, title, property ) :
def __init__( self, title, property, fallbackProperty ) :

GafferUI.PathColumn.__init__( self )

self.__title = title
self.__property = property
self.__fallbackProperty = fallbackProperty

def cellData( self, path, canceller = None ) :

cellValue = path.property( self.__property )
fallbackValue = path.property( self.__fallbackProperty )

data = self.CellData()

if cellValue & IECore.PathMatcher.Result.ExactMatch :
data.icon = "setMember.png"
elif cellValue & IECore.PathMatcher.Result.AncestorMatch :
data.icon = "setMemberFaded.png"
if cellValue is not None :
data.value = cellValue
elif fallbackValue is not None :
data.value = fallbackValue
data.foreground = imath.Color4f( 0.64, 0.64, 0.64, 1.0 )

if isinstance( data.value, ( imath.Color3f, imath.Color4f ) ) :
data.icon = data.value

return data

Expand Down Expand Up @@ -147,9 +154,7 @@ def __init__( self, inspector, scenePath, context, scriptNode, title=None, **kw
Gaffer.DictPath( {}, "/" ),
columns = (
_NodeNameColumn( "Node", "history:node", self.__scriptNode ),
_SetMembershipColumn( "Value", "history:value" ) if (
isinstance( inspector, GafferSceneUI.Private.SetMembershipInspector )
) else GafferUI.PathListingWidget.StandardColumn( "Value", "history:value" ),
_ValueColumn( "Value", "history:value", "history:fallbackValue" ),
_OperationIconColumn( "Operation", "history:operation" ),
),
sortable = False,
Expand Down
32 changes: 32 additions & 0 deletions python/GafferSceneUITest/AttributeInspectorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,38 @@ def testValue( self ) :
IECore.FloatData( 2.0 )
)

def testFallbackValue( self ) :

light = GafferSceneTest.TestLight()
group = GafferScene.Group()
group["in"][0].setInput( light["out"] )

groupFilter = GafferScene.PathFilter()
groupFilter["paths"].setValue( IECore.StringVectorData( [ "/group" ] ) )

glAttributes = GafferScene.OpenGLAttributes()
glAttributes["in"].setInput( group["out"] )
glAttributes["filter"].setInput( groupFilter["out"] )
glAttributes["attributes"]["visualiserScale"]["enabled"].setValue( True )
glAttributes["attributes"]["visualiserScale"]["value"].setValue( 2.0 )

# With no "gl:visualiser:scale" attribute at /group/light, the inspection returns
# the inherited attribute value with `sourceType` identifying it as a fallback.

inspection = self.__inspect( glAttributes["out"], "/group/light", "gl:visualiser:scale" )
self.assertEqual( inspection.value(), IECore.FloatData( 2.0 ) )
self.assertEqual( inspection.sourceType(), GafferSceneUI.Private.Inspector.Result.SourceType.Fallback )

# With a "gl:visualiser:scale" attribute created at the inspected location, it is
# returned instead of the inherited fallback.

light["visualiserAttributes"]["scale"]["enabled"].setValue( True )
light["visualiserAttributes"]["scale"]["value"].setValue( 4.0 )

inspection = self.__inspect( glAttributes["out"], "/group/light", "gl:visualiser:scale" )
self.assertEqual( inspection.value(), IECore.FloatData( 4.0 ) )
self.assertEqual( inspection.sourceType(), GafferSceneUI.Private.Inspector.Result.SourceType.Other )

def testSourceAndEdits( self ) :

s = Gaffer.ScriptNode()
Expand Down
77 changes: 77 additions & 0 deletions python/GafferSceneUITest/HistoryPathTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def testPropertyNames( self ) :
"fullName",
"name",
"history:value",
"history:fallbackValue",
"history:operation",
"history:source",
"history:editWarning",
Expand Down Expand Up @@ -247,20 +248,23 @@ def testProperties( self ) :
self.assertEqual( c[0].property( "name" ), str( c[0][-1] ) )
self.assertEqual( c[0].property( "history:node" ), s["testLight"] )
self.assertEqual( c[0].property( "history:value" ), 0.0 )
self.assertEqual( c[0].property( "history:fallbackValue" ), None )
self.assertEqual( c[0].property( "history:operation" ), Gaffer.TweakPlug.Mode.Create )
self.assertEqual( c[0].property( "history:source" ), s["testLight"]["parameters"]["exposure"] )
self.assertEqual( c[0].property( "history:editWarning" ), "" )

self.assertEqual( c[1].property( "name" ), str( c[1][-1] ) )
self.assertEqual( c[1].property( "history:node" ), s["tweaks"] )
self.assertEqual( c[1].property( "history:value" ), 2.0 )
self.assertEqual( c[1].property( "history:fallbackValue" ), None )
self.assertEqual( c[1].property( "history:operation" ), Gaffer.TweakPlug.Mode.Add )
self.assertEqual( c[1].property( "history:source" ), exposureTweak )
self.assertEqual( c[1].property( "history:editWarning" ), "" )

self.assertEqual( c[2].property( "name" ), str( c[2][-1] ) )
self.assertEqual( c[2].property( "history:node" ), s["editScope"]["LightEdits"]["ShaderTweaks"] )
self.assertEqual( c[2].property( "history:value" ), 3.0 )
self.assertEqual( c[2].property( "history:fallbackValue" ), None )
self.assertEqual( c[2].property( "history:operation" ), Gaffer.TweakPlug.Mode.Replace )
self.assertEqual( c[2].property( "history:source" ), edit )
self.assertEqual( c[2].property( "history:editWarning" ), "" )
Expand Down Expand Up @@ -354,6 +358,79 @@ def testEmptyHistory( self ) :

self.assertEqual( len( historyPath.children() ), 0 )

def testAttributeFallbackValues( self ) :

s = Gaffer.ScriptNode()

s["testLight"] = GafferSceneTest.TestLight()

s["group"] = GafferScene.Group()
s["group"]["in"][0].setInput( s["testLight"]["out"] )

s["groupFilter"] = GafferScene.PathFilter()
s["groupFilter"]["paths"].setValue( IECore.StringVectorData( [ "/group" ] ) )

s["tweaks"] = GafferScene.AttributeTweaks()
s["tweaks"]["in"].setInput( s["group"]["out"] )
s["tweaks"]["filter"].setInput( s["groupFilter"]["out"] )

groupTextureResolutionTweak = Gaffer.TweakPlug( "gl:visualiser:maxTextureResolution", 1024 )
groupTextureResolutionTweak["mode"].setValue( Gaffer.TweakPlug.Mode.Create )
s["tweaks"]["tweaks"].addChild( groupTextureResolutionTweak )

s["lightFilter"] = GafferScene.PathFilter()
s["lightFilter"]["paths"].setValue( IECore.StringVectorData( [ "/group/light" ] ) )

s["openGLAttributes"] = GafferScene.OpenGLAttributes()
s["openGLAttributes"]["in"].setInput( s["tweaks"]["out"] )
s["openGLAttributes"]["filter"].setInput( s["lightFilter"]["out"] )
s["openGLAttributes"]["attributes"]["visualiserMaxTextureResolution"]["enabled"].setValue( True )
s["openGLAttributes"]["attributes"]["visualiserMaxTextureResolution"]["value"].setValue( 1536 )

inspector = GafferSceneUI.Private.AttributeInspector(
s["openGLAttributes"]["out"], None, "gl:visualiser:maxTextureResolution",
)

with Gaffer.Context() as context :
context["scene:path"] = IECore.InternedStringVectorData( [ "group", "light" ] )
historyPath = inspector.historyPath()

c = historyPath.children()

self.assertEqual( c[0].property( "name" ), str( c[0][-1] ) )
self.assertEqual( c[0].property( "history:node" ), s["openGLAttributes"] )
self.assertEqual( c[0].property( "history:value" ), 1536 )
self.assertEqual( c[0].property( "history:fallbackValue" ), 1536 )
self.assertEqual( c[0].property( "history:operation" ), Gaffer.TweakPlug.Mode.Create )
self.assertEqual( c[0].property( "history:source" ), s["openGLAttributes"]["attributes"]["visualiserMaxTextureResolution"] )
self.assertEqual( c[0].property( "history:editWarning" ), "Edits to \"gl:visualiser:maxTextureResolution\" may affect other locations in the scene." )

s["openGLAttributes"]["enabled"].setValue( False )

with Gaffer.Context() as context :
context["scene:path"] = IECore.InternedStringVectorData( [ "group", "light" ] )
historyPath = inspector.historyPath()

c = historyPath.children()

self.assertEqual( c[0].property( "name" ), str( c[0][-1] ) )
self.assertEqual( c[0].property( "history:node" ), s["testLight"] )
self.assertEqual( c[0].property( "history:value" ), None )
self.assertEqual( c[0].property( "history:fallbackValue" ), None )
self.assertEqual( c[0].property( "history:operation" ), Gaffer.TweakPlug.Mode.Create )
self.assertEqual( c[0].property( "history:source" ), s["testLight"]["visualiserAttributes"]["maxTextureResolution"] )
self.assertEqual( c[0].property( "history:editWarning" ), "" )

# Disabling the openGLAttributes node results in its `visualiserMaxTextureResolution` plug remaining
# in the history but providing no value. We'll be able to see the value set on /group as the fallback
# value.
self.assertEqual( c[1].property( "name" ), str( c[1][-1] ) )
self.assertEqual( c[1].property( "history:node" ), s["openGLAttributes"] )
self.assertEqual( c[1].property( "history:value" ), None )
self.assertEqual( c[1].property( "history:fallbackValue" ), 1024 )
self.assertEqual( c[1].property( "history:operation" ), Gaffer.TweakPlug.Mode.Create )
self.assertEqual( c[1].property( "history:source" ), s["openGLAttributes"]["attributes"]["visualiserMaxTextureResolution"] )
self.assertEqual( c[1].property( "history:editWarning" ), "Edits to \"gl:visualiser:maxTextureResolution\" may affect other locations in the scene." )

if __name__ == "__main__":
unittest.main()
18 changes: 16 additions & 2 deletions python/GafferSceneUITest/SetMembershipInspectorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,21 @@ def testValue( self ) :

self.assertEqual(
self.__inspect( plane["out"], "/plane", "planeSet" ).value().value,
IECore.PathMatcher.Result.ExactMatch
True
)

def testFallbackValue( self ) :

plane = GafferScene.Plane()
group = GafferScene.Group()
group["sets"].setValue( "planeSet" )
group["in"][0].setInput( plane["out"] )

inspection = self.__inspect( group["out"], "/group/plane", "planeSet" )
self.assertEqual( inspection.value().value, True )
self.assertEqual(
inspection.sourceType(),
GafferSceneUI.Private.Inspector.Result.SourceType.Fallback
)

def testSourceAndEdits( self ) :
Expand Down Expand Up @@ -346,7 +360,7 @@ def testObjectSourceFallback( self ) :
self.__assertExpectedResult(
self.__inspect( plane["out"], "/plane", "planeSet" ),
source = plane["sets"],
sourceType = GafferSceneUI.Private.Inspector.Result.SourceType.Other,
sourceType = GafferSceneUI.Private.Inspector.Result.SourceType.Fallback,
editable = True
)

Expand Down
Loading

0 comments on commit 0831b50

Please sign in to comment.