diff --git a/Changes.md b/Changes.md index 9b969194603..9825fcdcf67 100644 --- a/Changes.md +++ b/Changes.md @@ -1,7 +1,11 @@ 1.4.15.x (relative to 1.4.15.1) ======== +Fixes +----- +- PathFilter : Fixed bug allowing dropping paths onto read-only `PathFilter` nodes in the graph. +- VectorDataWidget : Fixed bug allowing dropping paths onto read-only widgets. 1.4.15.1 (relative to 1.4.15.0) ======== diff --git a/python/GafferSceneUI/PathFilterUI.py b/python/GafferSceneUI/PathFilterUI.py index 7ade786a71e..5811eddde44 100644 --- a/python/GafferSceneUI/PathFilterUI.py +++ b/python/GafferSceneUI/PathFilterUI.py @@ -236,7 +236,7 @@ def __popupMenu( menuDefinition, plugValueWidget ) : GafferUI.Pointer.registerPointer( "removeObjects", GafferUI.Pointer( "removeObjects.png", imath.V2i( 53, 14 ) ) ) GafferUI.Pointer.registerPointer( "replaceObjects", GafferUI.Pointer( "replaceObjects.png", imath.V2i( 53, 14 ) ) ) -__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace" ] ) +__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace", "NotEditable" ] ) __originalDragPointer = None @@ -255,9 +255,14 @@ def __filterPlug( node ) : return filterPlugs[0] return None +def __editable( plug ) : + + return not Gaffer.MetadataAlgo.readOnly( plug ) and plug.settable() + def __dropMode( nodeGadget, event ) : - if __pathsPlug( nodeGadget.node() ) is None : + pathsPlug = __pathsPlug( nodeGadget.node() ) + if pathsPlug is None : filter = None filterPlug = __filterPlug( nodeGadget.node() ) @@ -267,9 +272,13 @@ def __dropMode( nodeGadget, event ) : if filterPlug.getInput() is not None : filter = filterPlug.source().node() if filter is None : - return __DropMode.Replace + return __DropMode.Replace if __editable( filterPlug ) else __DropMode.NotEditable elif not isinstance( filter, GafferScene.PathFilter ) : return __DropMode.None_ + pathsPlug = __pathsPlug( filter ) + + if not __editable( pathsPlug ) : + return __DropMode.NotEditable if event.modifiers & event.Modifiers.Shift : return __DropMode.Add @@ -342,7 +351,10 @@ def __dragMove( nodeGadget, event ) : if __originalDragPointer is None : return False - GafferUI.Pointer.setCurrent( __dropMode( nodeGadget, event ).name.lower() + "Objects" ) + dropMode = __dropMode( nodeGadget, event ) + GafferUI.Pointer.setCurrent( + dropMode.name.lower() + "Objects" if dropMode != __DropMode.NotEditable else "notEditable" + ) return True @@ -352,6 +364,9 @@ def __drop( nodeGadget, event ) : if __originalDragPointer is None : return False + if __dropMode( nodeGadget, event ) == __DropMode.NotEditable : + return True + pathsPlug = __pathsPlug( nodeGadget.node() ) if pathsPlug is None : pathsPlug = __pathsPlug( __filterPlug( nodeGadget.node() ).source().node() ) diff --git a/python/GafferSceneUI/SetFilterUI.py b/python/GafferSceneUI/SetFilterUI.py index 742f5363ae6..95d57d12818 100644 --- a/python/GafferSceneUI/SetFilterUI.py +++ b/python/GafferSceneUI/SetFilterUI.py @@ -111,7 +111,7 @@ GafferUI.Pointer.registerPointer( "removeSets", GafferUI.Pointer( "pointerRemoveSets.png", imath.V2i( 53, 14 ) ) ) GafferUI.Pointer.registerPointer( "replaceSets", GafferUI.Pointer( "pointerReplaceSets.png", imath.V2i( 53, 14 ) ) ) -__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace" ] ) +__DropMode = enum.Enum( "__DropMode", [ "None_", "Add", "Remove", "Replace", "NotEditable" ] ) __originalDragPointer = None @@ -146,13 +146,13 @@ def __dropMode( nodeGadget, event ) : if nodeGadget.node()["filter"].getInput() is not None : filter = nodeGadget.node()["filter"].source().node() if filter is None : - return __DropMode.Replace if __editable( nodeGadget.node()["filter"] ) else __DropMode.None_ + return __DropMode.Replace if __editable( nodeGadget.node()["filter"] ) else __DropMode.NotEditable elif not isinstance( filter, GafferScene.SetFilter ) : return __DropMode.None_ setsPlug = filter["setExpression"] if not __editable( setsPlug ) : - return __DropMode.None_ + return __DropMode.NotEditable if event.modifiers & event.Modifiers.Shift : return __DropMode.Add @@ -201,7 +201,10 @@ def __dragMove( nodeGadget, event ) : if __originalDragPointer is None : return False - GafferUI.Pointer.setCurrent( __dropMode( nodeGadget, event ).name.lower() + "Sets" ) + dropMode = __dropMode( nodeGadget, event ) + GafferUI.Pointer.setCurrent( + dropMode.name.lower() + "Sets" if dropMode != __DropMode.NotEditable else "notEditable" + ) return True @@ -211,6 +214,9 @@ def __drop( nodeGadget, event ) : if __originalDragPointer is None : return False + if __dropMode( nodeGadget, event ) == __DropMode.NotEditable : + return True + setsPlug = __setsPlug( nodeGadget.node() ) if setsPlug is None : setsPlug = __setsPlug( nodeGadget.node()["filter"].source().node() ) diff --git a/python/GafferUI/VectorDataWidget.py b/python/GafferUI/VectorDataWidget.py index da097cc5e85..483eed8f55e 100644 --- a/python/GafferUI/VectorDataWidget.py +++ b/python/GafferUI/VectorDataWidget.py @@ -621,6 +621,9 @@ def __addRows( self, button ) : def __dragEnter( self, widget, event ) : + if not self.getEditable() : + return False + if event.sourceWidget is self.__tableViewHolder and widget is not self.__buttonRow[1]: # we don't accept drags from ourself unless the target is the remove button return False