From 9ff42486b3925eb5217de66d5c0e04e1a6523094 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:14:06 -0700 Subject: [PATCH] LightEditor : Use InspectorColumn Remove the LightEditor specific implementation of InspectorColumn and replace with the general purpose GafferSceneUI::Private::InspectorColumn. --- Changes.md | 3 + python/GafferSceneUI/LightEditor.py | 18 +-- python/GafferSceneUITest/LightEditorTest.py | 2 +- .../LightEditorBinding.cpp | 132 +----------------- 4 files changed, 16 insertions(+), 139 deletions(-) diff --git a/Changes.md b/Changes.md index ed3783a941..822292ba3e 100644 --- a/Changes.md +++ b/Changes.md @@ -16,6 +16,9 @@ Improvements - Improved highlighting of active nodes, with more accurate tracking of Loop node iterations. - Annotation `{plug}` substitutions are now evaluated in a context determined relative to the focus node. - The strike-through for disabled nodes is now evaluated in a context determined relative to the focus node. +- LightEditor : + - Improved formatting of column headers containing whitespace. + - The "Double-click to toggle" tooltip is no longer displayed while hovering over non-editable cells, and a "Double-click to edit" tooltip is now displayed while hovering over other non-toggleable but editable cells. Fixes ----- diff --git a/python/GafferSceneUI/LightEditor.py b/python/GafferSceneUI/LightEditor.py index bc9c1d3d17..fa48906714 100644 --- a/python/GafferSceneUI/LightEditor.py +++ b/python/GafferSceneUI/LightEditor.py @@ -154,7 +154,7 @@ def registerParameter( cls, rendererKey, parameter, section = None, columnName = GafferSceneUI.LightEditor.registerColumn( rendererKey, ".".join( x for x in [ parameter.shader, parameter.name ] if x ), - lambda scene, editScope : _GafferSceneUI._LightEditorInspectorColumn( + lambda scene, editScope : GafferSceneUI.Private.InspectorColumn( GafferSceneUI.Private.ParameterInspector( scene, editScope, rendererKey, parameter ), columnName if columnName is not None else "" ), @@ -175,7 +175,7 @@ def registerShaderParameter( cls, rendererKey, parameter, shaderAttribute = None GafferSceneUI.LightEditor.registerColumn( rendererKey, ".".join( x for x in [ parameter.shader, parameter.name ] if x ), - lambda scene, editScope : _GafferSceneUI._LightEditorInspectorColumn( + lambda scene, editScope : GafferSceneUI.Private.InspectorColumn( GafferSceneUI.Private.ParameterInspector( scene, editScope, shaderAttribute, parameter ), columnName if columnName is not None else "" ), @@ -189,7 +189,7 @@ def registerAttribute( cls, rendererKey, attributeName, section = None ) : GafferSceneUI.LightEditor.registerColumn( rendererKey, attributeName, - lambda scene, editScope : _GafferSceneUI._LightEditorInspectorColumn( + lambda scene, editScope : GafferSceneUI.Private.InspectorColumn( GafferSceneUI.Private.AttributeInspector( scene, editScope, attributeName ), displayName ), @@ -199,7 +199,7 @@ def registerAttribute( cls, rendererKey, attributeName, section = None ) : # Registers a column in the Light Editor. # `inspectorFunction` is a callable object of the form # `inspectorFunction( scene, editScope )` returning a - # `GafferSceneUI._LightEditorInspectorColumn` object. + # `GafferSceneUI.Private.InspectorColumn` object. @classmethod def registerColumn( cls, rendererKey, columnKey, inspectorFunction, section = None ) : @@ -336,7 +336,7 @@ def __editSelectedCells( self, pathListing, quickBoolean = True ) : with Gaffer.Context( self.context() ) as context : for selection, column in zip( pathListing.getSelection(), pathListing.getColumns() ) : - if not isinstance( column, _GafferSceneUI._LightEditorInspectorColumn ) : + if not isinstance( column, GafferSceneUI.Private.InspectorColumn ) : continue for pathString in selection.paths() : path = GafferScene.ScenePlug.stringToPath( pathString ) @@ -441,7 +441,7 @@ def __disablableInspectionTweaks( self, pathListing ) : with Gaffer.Context( self.context() ) as context : for columnSelection, column in zip( pathListing.getSelection(), pathListing.getColumns() ) : - if not isinstance( column, _GafferSceneUI._LightEditorInspectorColumn ) : + if not isinstance( column, GafferSceneUI.Private.InspectorColumn ) : continue for path in columnSelection.paths() : context["scene:path"] = GafferScene.ScenePlug.stringToPath( path ) @@ -490,7 +490,7 @@ def __removableAttributeInspections( self, pathListing ) : with Gaffer.Context( self.context() ) as context : for columnSelection, column in zip( pathListing.getSelection(), pathListing.getColumns() ) : - if not isinstance( column, _GafferSceneUI._LightEditorInspectorColumn ) : + if not isinstance( column, GafferSceneUI.Private.InspectorColumn ) : continue elif not columnSelection.isEmpty() and type( column.inspector() ) != GafferSceneUI.Private.AttributeInspector : return [] @@ -533,7 +533,7 @@ def __selectedSetExpressions( self, pathListing ) : for columnSelection, column in zip( pathListing.getSelection(), pathListing.getColumns() ) : if ( not columnSelection.isEmpty() and ( - not isinstance( column, _GafferSceneUI._LightEditorInspectorColumn ) or + not isinstance( column, GafferSceneUI.Private.InspectorColumn ) or not ( Gaffer.Metadata.value( "attribute:" + column.inspector().name(), "ui:scene:acceptsSetName" ) or Gaffer.Metadata.value( "attribute:" + column.inspector().name(), "ui:scene:acceptsSetNames" ) or @@ -726,7 +726,7 @@ def __showHistory( self, *unused ) : for i in range( 0, len( columns ) ) : column = columns[ i ] - if not isinstance( column, _GafferSceneUI._LightEditorInspectorColumn ) : + if not isinstance( column, GafferSceneUI.Private.InspectorColumn ) : continue for path in selection[i].paths() : diff --git a/python/GafferSceneUITest/LightEditorTest.py b/python/GafferSceneUITest/LightEditorTest.py index fbbc7be7cb..18938f369d 100644 --- a/python/GafferSceneUITest/LightEditorTest.py +++ b/python/GafferSceneUITest/LightEditorTest.py @@ -751,7 +751,7 @@ def testShaderParameterEditScope( self ) : addAInspector = None exposureInspector = None for c in widget.getColumns() : - if not isinstance( c, _GafferSceneUI._LightEditorInspectorColumn ) : + if not isinstance( c, GafferSceneUI.Private.InspectorColumn ) : continue if c.headerData().value == "A" : addAInspector = c.inspector() diff --git a/src/GafferSceneUIModule/LightEditorBinding.cpp b/src/GafferSceneUIModule/LightEditorBinding.cpp index 1734a6dfe9..df5dd3ae9f 100644 --- a/src/GafferSceneUIModule/LightEditorBinding.cpp +++ b/src/GafferSceneUIModule/LightEditorBinding.cpp @@ -40,6 +40,7 @@ #include "GafferSceneUI/Private/AttributeInspector.h" #include "GafferSceneUI/Private/Inspector.h" +#include "GafferSceneUI/Private/InspectorColumn.h" #include "GafferSceneUI/Private/SetMembershipInspector.h" #include "GafferScene/ScenePath.h" @@ -170,112 +171,6 @@ class LocationNameColumn : public StandardPathColumn }; -const boost::container::flat_map g_sourceTypeColors = { - { (int)Inspector::Result::SourceType::Upstream, nullptr }, - { (int)Inspector::Result::SourceType::EditScope, new Color4fData( Imath::Color4f( 48, 100, 153, 150 ) / 255.0f ) }, - { (int)Inspector::Result::SourceType::Downstream, new Color4fData( Imath::Color4f( 239, 198, 24, 104 ) / 255.0f ) }, - { (int)Inspector::Result::SourceType::Other, nullptr }, - { (int)Inspector::Result::SourceType::Fallback, nullptr }, -}; -const Color4fDataPtr g_fallbackValueForegroundColor = new Color4fData( Imath::Color4f( 163, 163, 163, 255 ) / 255.0f ); - -class InspectorColumn : public PathColumn -{ - - public : - - IE_CORE_DECLAREMEMBERPTR( InspectorColumn ) - - InspectorColumn( GafferSceneUI::Private::InspectorPtr inspector, const std::string &columnName ) - : m_inspector( inspector ), m_headerValue( headerValue( columnName != "" ? columnName : inspector->name() ) ) - { - m_inspector->dirtiedSignal().connect( boost::bind( &InspectorColumn::inspectorDirtied, this ) ); - } - - GafferSceneUI::Private::Inspector *inspector() const - { - return m_inspector.get(); - } - - CellData cellData( const Gaffer::Path &path, const IECore::Canceller *canceller ) const override - { - CellData result; - - auto scenePath = runTimeCast( &path ); - if( !scenePath ) - { - return result; - } - - ScenePlug::PathScope scope( scenePath->getContext(), &scenePath->names() ); - scope.setCanceller( canceller ); - - Inspector::ConstResultPtr inspectorResult = m_inspector->inspect(); - if( !inspectorResult ) - { - return result; - } - - result.value = runTimeCast( inspectorResult->value() ); - /// \todo Should PathModel create a decoration automatically when we - /// return a colour for `Role::Value`? - result.icon = runTimeCast( inspectorResult->value() ); - result.background = g_sourceTypeColors.at( (int)inspectorResult->sourceType() ); - std::string toolTip; - if( inspectorResult->sourceType() == Inspector::Result::SourceType::Fallback ) - { - toolTip = "Source : " + inspectorResult->fallbackDescription(); - result.foreground = g_fallbackValueForegroundColor; - } - else if( auto source = inspectorResult->source() ) - { - toolTip = "Source : " + source->relativeName( source->ancestor() ); - } - - if( runTimeCast( result.value ) ) - { - toolTip += !toolTip.empty() ? "\n\nDouble-click to toggle" : "Double-click to toggle"; - } - - if( !toolTip.empty() ) - { - result.toolTip = new StringData( toolTip ); - } - - return result; - } - - CellData headerData( const IECore::Canceller *canceller ) const override - { - return CellData( m_headerValue ); - } - - private : - - void inspectorDirtied() - { - changedSignal()( this ); - } - - static IECore::ConstStringDataPtr headerValue( const std::string &inspectorName ) - { - std::string name = inspectorName; - // Convert from snake case and/or camel case to UI case. - if( name.find( '_' ) != std::string::npos ) - { - std::replace( name.begin(), name.end(), '_', ' ' ); - name = CamelCase::fromSpaced( name ); - } - return new StringData( CamelCase::toSpaced( name ) ); - } - - const InspectorPtr m_inspector; - const ConstStringDataPtr m_headerValue; - -}; - -/// \todo `MuteColumn` and `SetMembershipColumn` should not exist and we intend -/// to continue refactoring until it is possible to remove them entirely. class MuteColumn : public InspectorColumn { @@ -479,12 +374,6 @@ CompoundDataPtr SetMembershipColumn::m_setMemberUndefinedIconData = new Compound StringDataPtr SetMembershipColumn::m_setHasMembers = new StringData( "setMember.png" ); StringDataPtr SetMembershipColumn::m_setEmpty = new StringData( "muteLightUndefined.png" ); -PathColumn::CellData headerDataWrapper( PathColumn &pathColumn, const Canceller *canceller ) -{ - IECorePython::ScopedGILRelease gilRelease; - return pathColumn.headerData( canceller ); -} - } // namespace ////////////////////////////////////////////////////////////////////////// @@ -498,29 +387,16 @@ void GafferSceneUIModule::bindLightEditor() .def( init<>() ) ; - IECorePython::RefCountedClass( "_LightEditorInspectorColumn" ) - .def( init( - ( - arg_( "inspector" ), - arg_( "columName" ) = "" - ) - ) ) - .def( "inspector", &InspectorColumn::inspector, return_value_policy() ) - .def( "headerData", &headerDataWrapper, ( arg_( "canceller" ) = object() ) ) - ; - - IECorePython::RefCountedClass( "_LightEditorMuteColumn" ) + IECorePython::RefCountedClass( "_LightEditorMuteColumn" ) .def( init( ( arg_( "scene" ), arg_( "editScope" ) ) ) ) - .def( "inspector", &MuteColumn::inspector, return_value_policy() ) - .def( "headerData", &headerDataWrapper, ( arg_( "canceller" ) = object() ) ) ; - IECorePython::RefCountedClass( "_LightEditorSetMembershipColumn" ) + IECorePython::RefCountedClass( "_LightEditorSetMembershipColumn" ) .def( init( ( arg_( "scene" ), @@ -529,8 +405,6 @@ void GafferSceneUIModule::bindLightEditor() arg_( "columnName" ) ) ) ) - .def( "inspector", &SetMembershipColumn::inspector, return_value_policy() ) - .def( "headerData", &headerDataWrapper, ( arg_( "canceller" ) = object() ) ) ; }