diff --git a/include/GafferSceneUI/Private/Inspector.h b/include/GafferSceneUI/Private/Inspector.h index c4191e2389..576c75f4ba 100644 --- a/include/GafferSceneUI/Private/Inspector.h +++ b/include/GafferSceneUI/Private/Inspector.h @@ -183,6 +183,14 @@ class GAFFERSCENEUI_API Inspector : public IECore::RefCounted, public Gaffer::Si /// > that edits the processor itself. virtual EditFunctionOrFailure editFunction( Gaffer::EditScope *editScope, const GafferScene::SceneAlgo::History *history ) const; + using DisableEditFunction = std::function; + using DisableEditFunctionOrFailure = boost::variant; + /// Can be implemented to return a function that will disable an edit + /// at the specified plug. If this is not possible, should return an + /// error explaining why (this is typically due to `readOnly` metadata). + /// Called with `history->context` as the current context. + virtual DisableEditFunctionOrFailure disableEditFunction( Gaffer::ValuePlug *plug, const GafferScene::SceneAlgo::History *history ) const; + protected : Gaffer::EditScope *targetEditScope() const; @@ -343,6 +351,13 @@ class GAFFERSCENEUI_API Inspector::Result : public IECore::RefCounted /// by `acquireEdit()`. This should be displayed to the user. std::string editWarning() const; + /// Returns `true` if `disableEdit()` will disable the edit + /// at `source()`, and `false` otherwise. + bool canDisableEdit() const; + /// Disables the edit at `source()`. Throws if + /// `!canDisableEdit()` + void disableEdit() const; + private : Result( const IECore::ConstObjectPtr &value, const Gaffer::EditScopePtr &editScope ); @@ -359,6 +374,8 @@ class GAFFERSCENEUI_API Inspector::Result : public IECore::RefCounted EditFunctionOrFailure m_editFunction; std::string m_editWarning; + DisableEditFunctionOrFailure m_disableEditFunction; + }; } // namespace Private diff --git a/include/GafferSceneUI/Private/SetMembershipInspector.h b/include/GafferSceneUI/Private/SetMembershipInspector.h index 2363fd6179..b06507e064 100644 --- a/include/GafferSceneUI/Private/SetMembershipInspector.h +++ b/include/GafferSceneUI/Private/SetMembershipInspector.h @@ -82,6 +82,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; + DisableEditFunctionOrFailure disableEditFunction( Gaffer::ValuePlug *plug, const GafferScene::SceneAlgo::History *history ) const override; private : diff --git a/python/GafferSceneUI/_InspectorColumn.py b/python/GafferSceneUI/_InspectorColumn.py index dbfa6ccc30..d062eb09ab 100644 --- a/python/GafferSceneUI/_InspectorColumn.py +++ b/python/GafferSceneUI/_InspectorColumn.py @@ -176,22 +176,8 @@ def __disablableInspectionTweaks( pathListing ) : with inspectionContext : inspection = column.inspector().inspect() - if inspection is not None and inspection.editable() : - source = inspection.source() - editScope = inspection.editScope() - if ( - ( - ( - isinstance( source, ( Gaffer.TweakPlug, Gaffer.NameValuePlug ) ) and - source["enabled"].getValue() - ) or - isinstance( column.inspector(), GafferSceneUI.Private.SetMembershipInspector ) - ) and - ( editScope is None or editScope.isAncestorOf( source ) ) - ) : - tweaks.append( ( pathString, column.inspector() ) ) - else : - return [] + if inspection is not None and inspection.canDisableEdit() : + tweaks.append( inspection ) else : return [] @@ -199,20 +185,9 @@ def __disablableInspectionTweaks( pathListing ) : def __disableEdits( pathListing ) : - edits = __disablableInspectionTweaks( pathListing ) - path = pathListing.getPath().copy() with Gaffer.UndoScope( pathListing.ancestor( GafferUI.Editor ).scriptNode() ) : - for pathString, inspector in edits : - path.setFromString( pathString ) - with path.inspectionContext() : - inspection = inspector.inspect() - if inspection is not None and inspection.editable() : - source = inspection.source() - - if isinstance( source, ( Gaffer.TweakPlug, Gaffer.NameValuePlug ) ) : - source["enabled"].setValue( False ) - elif isinstance( inspector, GafferSceneUI.Private.SetMembershipInspector ) : - inspector.editSetMembership( inspection, pathString, GafferScene.EditScopeAlgo.SetMembership.Unchanged ) + for inspection in __disablableInspectionTweaks( pathListing ) : + inspection.disableEdit() def __removableAttributeInspections( pathListing ) : diff --git a/python/GafferSceneUITest/AttributeInspectorTest.py b/python/GafferSceneUITest/AttributeInspectorTest.py index e4774cb929..e53a1af567 100644 --- a/python/GafferSceneUITest/AttributeInspectorTest.py +++ b/python/GafferSceneUITest/AttributeInspectorTest.py @@ -846,5 +846,57 @@ def testAcquireEditCreateIfNecessary( self ) : self.assertIsNotNone( edit ) self.assertEqual( inspection.acquireEdit( createIfNecessary = False ), edit ) + def testDisableEdit( self ) : + + s = Gaffer.ScriptNode() + + s["light"] = GafferSceneTest.TestLight() + s["light"]["visualiserAttributes"]["scale"]["enabled"].setValue( True ) + + s["group"] = GafferScene.Group() + s["editScope1"] = Gaffer.EditScope() + + s["group"]["in"][0].setInput( s["light"]["out"] ) + + s["editScope1"].setup( s["group"]["out"] ) + s["editScope1"]["in"].setInput( s["group"]["out"] ) + + Gaffer.MetadataAlgo.setReadOnly( s["light"]["visualiserAttributes"]["scale"]["enabled"], True ) + inspection = self.__inspect( s["group"]["out"], "/group/light", "gl:visualiser:scale", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : light.visualiserAttributes.scale.enabled is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["light"]["visualiserAttributes"]["scale"]["enabled"], False ) + Gaffer.MetadataAlgo.setReadOnly( s["light"]["visualiserAttributes"]["scale"], True ) + inspection = self.__inspect( s["group"]["out"], "/group/light", "gl:visualiser:scale", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : light.visualiserAttributes.scale is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["light"]["visualiserAttributes"]["scale"], False ) + inspection = self.__inspect( s["group"]["out"], "/group/light", "gl:visualiser:scale", None ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( s["light"]["visualiserAttributes"]["scale"]["enabled"].getValue() ) + + lightEdit = GafferScene.EditScopeAlgo.acquireAttributeEdit( + s["editScope1"], "/group/light", "gl:visualiser:scale", createIfNecessary = True + ) + lightEdit["enabled"].setValue( True ) + lightEdit["value"].setValue( 2.0 ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], True ) + inspection = self.__inspect( s["editScope1"]["out"], "/group/light", "gl:visualiser:scale", s["editScope1"] ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : editScope1 is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], False ) + inspection = self.__inspect( s["editScope1"]["out"], "/group/light", "gl:visualiser:scale", s["editScope1"] ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( lightEdit["enabled"].getValue() ) + + inspection = self.__inspect( s["editScope1"]["out"], "/group/light", "gl:visualiser:scale", s["editScope1"] ) + self.assertFalse( inspection.canDisableEdit() ) + if __name__ == "__main__" : unittest.main() diff --git a/python/GafferSceneUITest/OptionInspectorTest.py b/python/GafferSceneUITest/OptionInspectorTest.py index 8b0aad86f5..99e2457807 100644 --- a/python/GafferSceneUITest/OptionInspectorTest.py +++ b/python/GafferSceneUITest/OptionInspectorTest.py @@ -918,5 +918,49 @@ def testAcquireEditCreateIfNecessary( self ) : self.assertIsNotNone( edit ) self.assertEqual( inspection.acquireEdit( createIfNecessary = False ), edit ) + def testDisableEdit( self ) : + + s = Gaffer.ScriptNode() + + s["standardOptions"] = GafferScene.StandardOptions() + s["standardOptions"]["options"]["renderCamera"]["enabled"].setValue( True ) + s["standardOptions"]["options"]["renderCamera"]["value"].setValue( "/defaultCamera" ) + + s["group"] = GafferScene.Group() + s["editScope1"] = Gaffer.EditScope() + + s["group"]["in"][0].setInput( s["standardOptions"]["out"] ) + + s["editScope1"].setup( s["group"]["out"] ) + s["editScope1"]["in"].setInput( s["group"]["out"] ) + + Gaffer.MetadataAlgo.setReadOnly( s["standardOptions"]["options"], True ) + inspection = self.__inspect( s["group"]["out"], "render:camera", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : standardOptions.options is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["standardOptions"]["options"], False ) + inspection = self.__inspect( s["group"]["out"], "render:camera", None ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( s["standardOptions"]["options"]["renderCamera"]["enabled"].getValue() ) + + cameraEdit = GafferScene.EditScopeAlgo.acquireOptionEdit( + s["editScope1"], "render:camera", createIfNecessary = True + ) + cameraEdit["enabled"].setValue( True ) + cameraEdit["value"].setValue( "/bar" ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], True ) + inspection = self.__inspect( s["editScope1"]["out"], "render:camera", s["editScope1"] ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : editScope1 is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], False ) + inspection = self.__inspect( s["editScope1"]["out"], "render:camera", s["editScope1"] ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( cameraEdit["enabled"].getValue() ) + if __name__ == "__main__" : unittest.main() diff --git a/python/GafferSceneUITest/ParameterInspectorTest.py b/python/GafferSceneUITest/ParameterInspectorTest.py index 687bf03d59..85b9b94389 100644 --- a/python/GafferSceneUITest/ParameterInspectorTest.py +++ b/python/GafferSceneUITest/ParameterInspectorTest.py @@ -416,6 +416,62 @@ def testAcquireEditCreateIfNecessary( self ) : self.assertIsNotNone( edit ) self.assertEqual( inspection.acquireEdit( createIfNecessary = False ), edit ) + def testDisableEdit( self ) : + + s = Gaffer.ScriptNode() + + s["light"] = GafferSceneTest.TestLight() + + s["lightFilter"] = GafferScene.PathFilter() + s["lightFilter"]["paths"].setValue( IECore.StringVectorData( [ "/light" ] ) ) + + s["shaderTweaks"] = GafferScene.ShaderTweaks() + s["shaderTweaks"]["in"].setInput( s["light"]["out"] ) + s["shaderTweaks"]["filter"].setInput( s["lightFilter"]["out"] ) + exposureTweak = Gaffer.TweakPlug( "exposure", 10 ) + s["shaderTweaks"]["tweaks"].addChild( exposureTweak ) + + s["editScope"] = Gaffer.EditScope() + s["editScope"].setup( s["shaderTweaks"]["out"] ) + s["editScope"]["in"].setInput( s["shaderTweaks"]["out"] ) + + Gaffer.MetadataAlgo.setReadOnly( exposureTweak["enabled"], True ) + inspection = self.__inspect( s["shaderTweaks"]["out"], "/light", "exposure", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : shaderTweaks.tweaks.tweak.enabled is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( exposureTweak["enabled"], False ) + Gaffer.MetadataAlgo.setReadOnly( exposureTweak, True ) + inspection = self.__inspect( s["shaderTweaks"]["out"], "/light", "exposure", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : shaderTweaks.tweaks.tweak is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( exposureTweak, False ) + inspection = self.__inspect( s["shaderTweaks"]["out"], "/light", "exposure", None ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( exposureTweak["enabled"].getValue() ) + + lightEdit = GafferScene.EditScopeAlgo.acquireParameterEdit( + s["editScope"], "/light", "light", ( "", "exposure" ), createIfNecessary = True + ) + lightEdit["enabled"].setValue( True ) + lightEdit["value"].setValue( 2.0 ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope"], True ) + inspection = self.__inspect( s["editScope"]["out"], "/light", "exposure", s["editScope"] ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : editScope is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope"], False ) + inspection = self.__inspect( s["editScope"]["out"], "/light", "exposure", s["editScope"] ) + self.assertTrue( inspection.canDisableEdit() ) + inspection.disableEdit() + self.assertFalse( lightEdit["enabled"].getValue() ) + + inspection = self.__inspect( s["editScope"]["out"], "/light", "exposure", s["editScope"] ) + self.assertFalse( inspection.canDisableEdit() ) + def testDisabledTweaks( self ) : light = GafferSceneTest.TestLight() diff --git a/python/GafferSceneUITest/SetMembershipInspectorTest.py b/python/GafferSceneUITest/SetMembershipInspectorTest.py index 9af8e562b6..1ebd6e03ae 100644 --- a/python/GafferSceneUITest/SetMembershipInspectorTest.py +++ b/python/GafferSceneUITest/SetMembershipInspectorTest.py @@ -618,5 +618,67 @@ def testAcquireEditCreateIfNecessary( self ) : self.assertIsNotNone( edit ) self.assertEqual( inspection.acquireEdit( createIfNecessary = False ), edit ) + def testDisableEdit( self ) : + + s = Gaffer.ScriptNode() + + s["plane"] = GafferScene.Plane() + s["plane"]["sets"].setValue( "planeSetA planeSetB" ) + + s["group"] = GafferScene.Group() + + s["editScope1"] = Gaffer.EditScope() + + s["group"]["in"][0].setInput( s["plane"]["out"] ) + + Gaffer.MetadataAlgo.setReadOnly( s["plane"]["sets"], True ) + inspection = self.__inspect( s["group"]["out"], "/group/plane", "planeSetA", None ) + self.assertFalse( inspection.canDisableEdit() ) + + Gaffer.MetadataAlgo.setReadOnly( s["plane"]["sets"], False ) + inspection = self.__inspect( s["group"]["out"], "/group/plane", "planeSetA", None ) + self.assertTrue( inspection.canDisableEdit() ) + + inspection.disableEdit() + self.assertEqual( s["plane"]["sets"].getValue(), "planeSetB" ) + + inspection = self.__inspect( s["group"]["out"], "/group/plane", "planeSetB", None ) + self.assertTrue( inspection.canDisableEdit() ) + + inspection.disableEdit() + self.assertEqual( s["plane"]["sets"].getValue(), "" ) + + s["editScope1"].setup( s["group"]["out"] ) + s["editScope1"]["in"].setInput( s["group"]["out"] ) + + for membership in ( GafferScene.EditScopeAlgo.SetMembership.Added, GafferScene.EditScopeAlgo.SetMembership.Removed ) : + + GafferScene.EditScopeAlgo.setSetMembership( + s["editScope1"], + IECore.PathMatcher( [ "group/plane" ] ), + "planeSetEditScope", + membership + ) + + self.assertEqual( + GafferScene.EditScopeAlgo.getSetMembership( s["editScope1"], "/group/plane", "planeSetEditScope"), + membership + ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], True ) + inspection = self.__inspect( s["editScope1"]["out"], "/group/plane", "planeSetEditScope", None ) + self.assertFalse( inspection.canDisableEdit() ) + self.assertRaisesRegex( IECore.Exception, "Cannot disable edit : editScope1 is locked.", inspection.disableEdit ) + + Gaffer.MetadataAlgo.setReadOnly( s["editScope1"], False ) + inspection = self.__inspect( s["editScope1"]["out"], "/group/plane", "planeSetEditScope", None ) + self.assertTrue( inspection.canDisableEdit() ) + + inspection.disableEdit() + self.assertEqual( + GafferScene.EditScopeAlgo.getSetMembership( s["editScope1"], "/group/plane", "planeSetEditScope"), + GafferScene.EditScopeAlgo.SetMembership.Unchanged + ) + if __name__ == "__main__" : unittest.main() \ No newline at end of file diff --git a/src/GafferSceneUI/Inspector.cpp b/src/GafferSceneUI/Inspector.cpp index 2853123251..f48896ec0e 100644 --- a/src/GafferSceneUI/Inspector.cpp +++ b/src/GafferSceneUI/Inspector.cpp @@ -38,6 +38,7 @@ #include "Gaffer/Animation.h" #include "Gaffer/MetadataAlgo.h" +#include "Gaffer/OptionalValuePlug.h" #include "Gaffer/PathFilter.h" #include "Gaffer/ScriptNode.h" #include "Gaffer/Spreadsheet.h" @@ -296,6 +297,8 @@ void Inspector::inspectHistoryWalk( const GafferScene::SceneAlgo::History *histo { result->m_editFunction = nonEditableReason; } + + result->m_disableEditFunction = disableEditFunction( result->m_source.get(), history ); } } } @@ -368,6 +371,39 @@ Inspector::EditFunctionOrFailure Inspector::editFunction( Gaffer::EditScope *edi return "Editing not supported"; } +Inspector::DisableEditFunctionOrFailure Inspector::disableEditFunction( Gaffer::ValuePlug *plug, const GafferScene::SceneAlgo::History *history ) const +{ + Gaffer::BoolPlugPtr enabledPlug; + if( auto tweakPlug = runTimeCast( plug ) ) + { + enabledPlug = tweakPlug->enabledPlug(); + } + else if( auto nameValuePlug = runTimeCast( plug ) ) + { + enabledPlug = nameValuePlug->enabledPlug(); + } + else if( auto optionalValuePlug = runTimeCast( plug ) ) + { + enabledPlug = optionalValuePlug->enabledPlug(); + } + + if( enabledPlug ) + { + if( const GraphComponent *readOnlyReason = MetadataAlgo::readOnlyReason( enabledPlug.get() ) ) + { + return fmt::format( "{} is locked.", readOnlyReason->relativeName( readOnlyReason->ancestor() ) ); + } + else + { + return [ enabledPlug ] () { enabledPlug->setValue( false ); }; + } + } + else + { + return "Disabling edits not supported"; + } +} + IECore::ConstObjectPtr Inspector::fallbackValue( const GafferScene::SceneAlgo::History *history, std::string &description ) const { return nullptr; @@ -676,6 +712,21 @@ Gaffer::ValuePlugPtr Inspector::Result::acquireEdit( bool createIfNecessary ) co throw IECore::Exception( "Not editable : " + boost::get( m_editFunction ) ); } +bool Inspector::Result::canDisableEdit() const +{ + return m_disableEditFunction.which() == 0 && boost::get( m_disableEditFunction ) != nullptr; +} + +void Inspector::Result::disableEdit() const +{ + if( m_disableEditFunction.which() == 0 ) + { + return boost::get( m_disableEditFunction )(); + } + + throw IECore::Exception( "Cannot disable edit : " + boost::get( m_disableEditFunction ) ); +} + std::string Inspector::Result::editWarning() const { return m_editWarning; diff --git a/src/GafferSceneUI/SetMembershipInspector.cpp b/src/GafferSceneUI/SetMembershipInspector.cpp index f4d35d35d0..a4271ac4a5 100644 --- a/src/GafferSceneUI/SetMembershipInspector.cpp +++ b/src/GafferSceneUI/SetMembershipInspector.cpp @@ -127,29 +127,8 @@ HistoryCache g_historyCache( ); -} // namespace - -SetMembershipInspector::SetMembershipInspector( - const GafferScene::ScenePlugPtr &scene, - const Gaffer::PlugPtr &editScope, - IECore::InternedString setName -) : -Inspector( "setMembership", setName.string(), editScope ), -m_scene( scene ), -m_setName( setName ) -{ - m_scene->node()->plugDirtiedSignal().connect( - boost::bind( &SetMembershipInspector::plugDirtied, this, ::_1 ) - ); - - Metadata::plugValueChangedSignal().connect( boost::bind( &SetMembershipInspector::plugMetadataChanged, this, ::_3, ::_4 ) ); - Metadata::nodeValueChangedSignal().connect( boost::bind( &SetMembershipInspector::nodeMetadataChanged, this, ::_2, ::_3 ) ); -} - -bool SetMembershipInspector::editSetMembership( const Result *inspection, const ScenePlug::ScenePath &path, EditScopeAlgo::SetMembership setMembership ) const +bool editSetMembership( Gaffer::Plug *plug, const std::string &setName, const ScenePlug::ScenePath &path, EditScopeAlgo::SetMembership setMembership ) { - PlugPtr plug = inspection->acquireEdit(); - if( auto objectNode = runTimeCast( plug->node() ) ) { std::vector sets; @@ -157,14 +136,14 @@ bool SetMembershipInspector::editSetMembership( const Result *inspection, const if( setMembership == EditScopeAlgo::SetMembership::Added ) { - if( std::find( sets.begin(), sets.end(), m_setName.string() ) == sets.end() ) + if( std::find( sets.begin(), sets.end(), setName ) == sets.end() ) { - sets.push_back( m_setName.string() ); + sets.push_back( setName ); } } else { - sets.erase( std::remove( sets.begin(), sets.end(), m_setName.string() ), sets.end() ); + sets.erase( std::remove( sets.begin(), sets.end(), setName ), sets.end() ); } objectNode->setsPlug()->setValue( boost::algorithm::join( sets, " " ) ); @@ -183,7 +162,7 @@ bool SetMembershipInspector::editSetMembership( const Result *inspection, const EditScopeAlgo::setSetMembership( editScope, m, - m_setName.string(), + setName, setMembership ); @@ -194,6 +173,30 @@ bool SetMembershipInspector::editSetMembership( const Result *inspection, const return false; } +} // namespace + +SetMembershipInspector::SetMembershipInspector( + const GafferScene::ScenePlugPtr &scene, + const Gaffer::PlugPtr &editScope, + IECore::InternedString setName +) : +Inspector( "setMembership", setName.string(), editScope ), +m_scene( scene ), +m_setName( setName ) +{ + m_scene->node()->plugDirtiedSignal().connect( + boost::bind( &SetMembershipInspector::plugDirtied, this, ::_1 ) + ); + + Metadata::plugValueChangedSignal().connect( boost::bind( &SetMembershipInspector::plugMetadataChanged, this, ::_3, ::_4 ) ); + Metadata::nodeValueChangedSignal().connect( boost::bind( &SetMembershipInspector::nodeMetadataChanged, this, ::_2, ::_3 ) ); +} + +bool SetMembershipInspector::editSetMembership( const Result *inspection, const ScenePlug::ScenePath &path, EditScopeAlgo::SetMembership setMembership ) const +{ + return ::editSetMembership( inspection->acquireEdit().get(), m_setName.string(), path, setMembership ); +} + GafferScene::SceneAlgo::History::ConstPtr SetMembershipInspector::history() const { if( !m_scene->existsPlug()->getValue() ) @@ -319,6 +322,24 @@ Inspector::EditFunctionOrFailure SetMembershipInspector::editFunction( Gaffer::E } } +Inspector::DisableEditFunctionOrFailure SetMembershipInspector::disableEditFunction( Gaffer::ValuePlug *plug, const GafferScene::SceneAlgo::History *history ) const +{ + if( const GraphComponent *readOnlyReason = MetadataAlgo::readOnlyReason( plug ) ) + { + return fmt::format( "{} is locked.", readOnlyReason->relativeName( readOnlyReason->ancestor() ) ); + } + else + { + return [ + plug, + setName = m_setName, + path = history->context->get( ScenePlug::scenePathContextName ) + ] () { + return ::editSetMembership( plug, setName.string(), path, EditScopeAlgo::SetMembership::Unchanged ); + }; + } +} + void SetMembershipInspector::plugDirtied( Gaffer::Plug *plug ) { if( plug == m_scene->setPlug() ) diff --git a/src/GafferSceneUIModule/InspectorBinding.cpp b/src/GafferSceneUIModule/InspectorBinding.cpp index f897b0e6d9..bf2d61ca33 100644 --- a/src/GafferSceneUIModule/InspectorBinding.cpp +++ b/src/GafferSceneUIModule/InspectorBinding.cpp @@ -78,6 +78,12 @@ Gaffer::ValuePlugPtr acquireEditWrapper( GafferSceneUI::Private::Inspector::Resu return result.acquireEdit( createIfNecessary ); } +void disableEditWrapper( GafferSceneUI::Private::Inspector::Result &result ) +{ + ScopedGILRelease gilRelease; + return result.disableEdit(); +} + bool editSetMembershipWrapper( const GafferSceneUI::Private::SetMembershipInspector &inspector, const GafferSceneUI::Private::Inspector::Result &inspection, @@ -135,6 +141,8 @@ void GafferSceneUIModule::bindInspector() .def( "nonEditableReason", &Inspector::Result::nonEditableReason ) .def( "acquireEdit", &acquireEditWrapper, ( arg( "createIfNecessary" ) = true ) ) .def( "editWarning", &Inspector::Result::editWarning ) + .def( "canDisableEdit", &Inspector::Result::canDisableEdit ) + .def( "disableEdit", &disableEditWrapper ) ; enum_( "SourceType" )