Skip to content

Commit 97b1c8b

Browse files
Merge pull request #6531 from murraystevenson/sceneInspectorRevampDrag
SceneInspector Revamp : Small UI Improvements
2 parents e78a977 + 3acbb40 commit 97b1c8b

File tree

4 files changed

+121
-11
lines changed

4 files changed

+121
-11
lines changed

Changes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ Improvements
55
------------
66

77
- RenderMan : Added dedicated viewport visualisers for RenderMan lights.
8+
- SceneInspector :
9+
- Cells dragged from the "Name" column now return their name, rather than their full path [^1].
10+
- Nodes can be pinned for comparison by dropping them onto the green "B" side of the "Scene" comparison header [^1].
11+
- The current expansion is now preserved when enabling or disabling comparison mode [^1].
12+
13+
Fixes
14+
-----
15+
16+
- PathListingWidget : Columns set to automatically stretch now equally share available space when a PathListingWidget's columns are updated via `setColumns()`.
817

918
Fixes
1019
-----

python/GafferSceneUI/SceneInspector.py

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,14 @@ def __init__( self, scriptNode, **kw ) :
131131

132132
self.settings()["compare"]["scene"]["value"].setInput( self.settings()["in"] )
133133

134+
nameColumn = GafferUI.StandardPathColumn( "Name", "name" )
134135
self.__standardColumns = [
135-
GafferUI.StandardPathColumn( "Name", "name" ),
136+
nameColumn,
136137
GafferSceneUI.Private.InspectorColumn( "inspector:inspector", headerData = GafferUI.PathColumn.CellData( value = "Value" ) ),
137138
]
138139

139140
self.__diffColumns = [
140-
GafferUI.StandardPathColumn( "Name", "name" ),
141+
nameColumn,
141142
_GafferSceneUI._SceneInspector.InspectorDiffColumn( _GafferSceneUI._SceneInspector.InspectorDiffColumn.DiffContext.A ),
142143
_GafferSceneUI._SceneInspector.InspectorDiffColumn( _GafferSceneUI._SceneInspector.InspectorDiffColumn.DiffContext.B ),
143144
]
@@ -176,6 +177,7 @@ def __init__( self, scriptNode, **kw ) :
176177
displayMode = GafferUI.PathListingWidget.DisplayMode.Tree,
177178
sortable = False,
178179
)
180+
self.__locationPathListing.dragBeginSignal().connectFront( Gaffer.WeakMethod( self.__dragBegin ) )
179181

180182
with GafferUI.ListContainer( spacing = 4, borderWidth = 4, parenting = { "label" : "Globals" } ) :
181183

@@ -195,6 +197,7 @@ def __init__( self, scriptNode, **kw ) :
195197
displayMode = GafferUI.PathListingWidget.DisplayMode.Tree,
196198
sortable = False,
197199
)
200+
self.__globalsPathListing.dragBeginSignal().connectFront( Gaffer.WeakMethod( self.__dragBegin ) )
198201

199202
GafferSceneUI.ScriptNodeAlgo.selectedPathsChangedSignal( scriptNode ).connect(
200203
Gaffer.WeakMethod( self.__selectedPathsChanged )
@@ -285,6 +288,16 @@ def __updateFilter( self, tree, plug ) :
285288

286289
tree.setFilter( pattern )
287290

291+
def __dragBegin( self, widget, event ) :
292+
293+
assert( widget in ( self.__locationPathListing, self.__globalsPathListing ) )
294+
# Return leaf names rather than full paths when dragging from the Name column.
295+
## \todo Support creation of columns in other editors by dragging attributes/options/etc
296+
# from the Scene Inspector.
297+
selection = widget.getSelection()[0]
298+
if not selection.isEmpty() :
299+
return IECore.StringVectorData( [ path.split( "/" )[-1] for path in selection.paths() ] )
300+
288301
GafferUI.Editor.registerType( "SceneInspector", SceneInspector )
289302

290303
# InspectorTree isn't public API. Expose the `registerInspectors()` function on SceneInspector
@@ -555,9 +568,9 @@ def __init__( self, plug, **kw ) :
555568
self.__icon._qtWidget().setFixedWidth( 13 )
556569
self.__icon.buttonPressSignal().connect( Gaffer.WeakMethod( self.__showFocusMenu ) )
557570

558-
menuButton = GafferUI.Button( image="menuIndicator.png", hasFrame=False, highlightOnOver=False )
559-
menuButton._qtWidget().setObjectName( "menuDownArrow" )
560-
menuButton.buttonPressSignal().connect( Gaffer.WeakMethod( self.__showFocusMenu ) )
571+
self.__menuButton = GafferUI.Button( image="menuIndicator.png", hasFrame=False, highlightOnOver=False )
572+
self.__menuButton._qtWidget().setObjectName( "menuDownArrow" )
573+
self.__menuButton.buttonPressSignal().connect( Gaffer.WeakMethod( self.__showFocusMenu ) )
561574

562575
self.__nodeSetChangedSignal = GafferUI.WidgetSignal()
563576

@@ -604,6 +617,11 @@ def nodeSetChangedSignal( self ) :
604617

605618
return self.__nodeSetChangedSignal
606619

620+
def setHighlighted( self, highlighted ) :
621+
622+
self.__icon.setHighlighted( highlighted )
623+
self.__menuButton.setHighlighted( highlighted )
624+
607625
def __updateInput( self, *unused ) :
608626

609627
input = None
@@ -745,8 +763,50 @@ def __init__( self, plug, **kw ) :
745763

746764
with row :
747765
labelWidget = _InputLabelWidget()
748-
focusWidget = _FocusPlugValueWidget( plug )
749-
labelWidget.connectToNodeSetWidget( focusWidget )
766+
self.__focusWidget = _FocusPlugValueWidget( plug )
767+
labelWidget.connectToNodeSetWidget( self.__focusWidget )
768+
769+
self.dragEnterSignal().connectFront( Gaffer.WeakMethod( self.__dragEnter ) )
770+
self.dragLeaveSignal().connectFront( Gaffer.WeakMethod( self.__dragLeave ) )
771+
self.dropSignal().connectFront( Gaffer.WeakMethod( self.__drop ) )
772+
773+
def __dropNode( self, event ) :
774+
775+
if isinstance( event.data, Gaffer.Node ) :
776+
return event.data
777+
elif isinstance( event.data, Gaffer.Set ) :
778+
for node in reversed( event.data ):
779+
if isinstance( node, Gaffer.Node ) :
780+
return node
781+
else:
782+
return None
783+
784+
def __dragEnter( self, widget, event ) :
785+
786+
if self.isAncestorOf( event.sourceWidget ) :
787+
return False
788+
789+
if self.__dropNode( event ) :
790+
self.__focusWidget.setHighlighted( True )
791+
792+
return True
793+
794+
def __dragLeave( self, widget, event ) :
795+
796+
self.__focusWidget.setHighlighted( False )
797+
798+
return True
799+
800+
def __drop( self, widget, event ) :
801+
802+
node = self.__dropNode( event )
803+
804+
if node :
805+
self.__focusWidget.setNodeSet( nodeSet = Gaffer.StandardSet( [ node ] ) )
806+
807+
self.__focusWidget.setHighlighted( False )
808+
809+
return True
750810

751811
# Simple widget that just displays the `renderPass` variable from
752812
# the current context.

python/GafferUI/PathListingWidget.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ def updateColumnWidths( self, columnsChanged = False ) :
11671167
if columnWidthsChanged or columnsChanged :
11681168
# The space available for stretch columns may have changed, so
11691169
# adjust them to fit.
1170-
self.__resizeStretchColumns()
1170+
self.__resizeStretchColumns( columnsChanged )
11711171

11721172
if stretchLastColumn :
11731173
# finally, resize the last column to make use of any remaining available width
@@ -1332,7 +1332,7 @@ def __resizeLastColumnToAvailableWidth( self, minimumSuggestedWidth = 0 ) :
13321332
header.resizeSection( lastColumn, adjustedWidth )
13331333
self.__recalculatingColumnWidths = False
13341334

1335-
def __resizeStretchColumns( self ) :
1335+
def __resizeStretchColumns( self, columnsChanged = False ) :
13361336

13371337
header = self.header()
13381338
availableWidth = self.viewport().width()
@@ -1359,8 +1359,12 @@ def __resizeStretchColumns( self ) :
13591359

13601360
weight = 1.0 / len( columnsToStretch )
13611361
for c in columnsToStretch :
1362-
if stretchColumnWidth > 0 :
1363-
# preserve any existing column proportions
1362+
if stretchColumnWidth > 0 and not columnsChanged :
1363+
# preserve any existing column proportions when resizing
1364+
# existing columns if the columns haven't changed. If
1365+
# the columns have changed then we're better off equally
1366+
# assigning the available space rather than preserving any
1367+
# existing header widths.
13641368
weight = header.sectionSize( c ) / stretchColumnWidth
13651369

13661370
## \todo A very small resize with multiple stretch columns can result in the

python/GafferUITest/PathListingWidgetTest.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,6 +1624,43 @@ def testColumnWidthsWhenRemovingLastColumn( self ) :
16241624
widget.setColumns( widget.getColumns()[:-1] )
16251625
self.assertEqual( widget._qtWidget().header().length(), widget._qtWidget().viewport().width() )
16261626

1627+
def testStretchColumnWidthsWhenUpdatingColumns( self ) :
1628+
1629+
with GafferUI.Window() as window :
1630+
widget = GafferUI.PathListingWidget(
1631+
path = Gaffer.DictPath( {}, "/" ),
1632+
displayMode = GafferUI.PathListingWidget.DisplayMode.List,
1633+
columns = [
1634+
GafferUI.PathListingWidget.StandardColumn( "Test", "test" ),
1635+
GafferUI.PathListingWidget.StandardColumn( "Test", "test", sizeMode = GafferUI.PathColumn.SizeMode.Stretch )
1636+
]
1637+
)
1638+
1639+
window._qtWidget().resize( 512, 384 )
1640+
window.setVisible( True )
1641+
1642+
self.waitForIdle( 1000 )
1643+
1644+
widget.setColumns( [
1645+
GafferUI.PathListingWidget.StandardColumn( "Test", "test" ),
1646+
GafferUI.PathListingWidget.StandardColumn( "Test", "test", sizeMode = GafferUI.PathColumn.SizeMode.Stretch ),
1647+
GafferUI.PathListingWidget.StandardColumn( "Test", "test", sizeMode = GafferUI.PathColumn.SizeMode.Stretch )
1648+
] )
1649+
1650+
self.waitForIdle( 1000 )
1651+
1652+
# Our two Stretch columns should equally share the available space
1653+
self.assertEqual( widget._qtWidget().header().sectionSize( 1 ), widget._qtWidget().header().sectionSize( 2 ) )
1654+
self.assertAlmostEqual(
1655+
widget._qtWidget().header().sectionSize( 1 ) + widget._qtWidget().header().sectionSize( 2 ),
1656+
widget._qtWidget().viewport().width() - widget._qtWidget().header().sectionSize( 0 ),
1657+
## \todo If the available space is an odd number of pixels, we require this delta as `_TreeView.__resizeStretchColumns`
1658+
# will resize both stretch columns to the same width and leave the remaining pixel. We should update `_TreeView.__resizeStretchColumns`
1659+
# to use _all_ available space, though this will require moving this delta to the previous assertion as the resulting column
1660+
# widths could then differ by 1...
1661+
delta = 1
1662+
)
1663+
16271664
def testColumnSizeSurvivesStylesheetUpdate( self ) :
16281665

16291666
for visible in ( False, True ) :

0 commit comments

Comments
 (0)