Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
1.6.x.x (relative to 1.6.6.0)
=======

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

- ShaderTweaks : Improved support for creating tweaks via drag & drop from the SceneInspector to the `+` button.
- Dragging a parameter name or value now creates a tweak containing both the parameter name and value.
- Multiple parameter names and/or values can be dragged to create multiple tweaks.
- Parameters dragged from non-output shaders create tweaks that include the shader name to correctly identify the parameter.

Fixes
-----

Expand Down
53 changes: 48 additions & 5 deletions python/GafferSceneUI/SceneInspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import imath

import IECore
import IECoreScene

import Gaffer
import GafferScene
Expand Down Expand Up @@ -248,25 +249,67 @@ def __draggedInspections( dragDropEvent, inspectorType ) :
if not isinstance( pathListing, GafferUI.PathListingWidget ) :
return None

if pathListing.ancestor( GafferSceneUI.SceneInspector ) is None :
sceneInspector = pathListing.ancestor( GafferSceneUI.SceneInspector )
if sceneInspector is None :
return None

columnSelection = {
column : selection for column, selection in zip( pathListing.getColumns(), pathListing.getSelection() )
if isinstance( column, GafferSceneUI.Private.InspectorColumn )
}
firstInspectorColumn = next( iter( columnSelection ), None )
if firstInspectorColumn is None :
return None

selection = IECore.PathMatcher()
for s in pathListing.getSelection() :
selection.addPaths( s )

result = {}
valueColumn = pathListing.getColumns()[1]
path = pathListing.getPath().copy()
for p in pathListing.visualOrder( selection ) :
path.setFromString( p )
valueColumn = next(
( column for column, selection in columnSelection.items() if selection.match( p ) & IECore.PathMatcher.Result.ExactMatch ),
firstInspectorColumn
)
inspector = valueColumn.inspector( path )
if isinstance( inspector, inspectorType ) :
value = valueColumn.inspect( path )
result[ path[-1] ] = value.value() if value is not None else None
if not isinstance( inspector, inspectorType ) :
continue

if inspectorType == GafferSceneUI.Private.ParameterInspector :
name = SceneInspector.__shaderParameterName( inspector.parameter(), sceneInspector.settings()["in"], valueColumn, path )
else :
name = path[-1]

value = valueColumn.inspect( path )
result[name] = value.value() if value is not None else None

return result

@staticmethod
def __shaderParameterName( parameter, scene, column, path ) :

name = parameter.name
context = column.inspectorContext( path )
if "scene:path" not in context :
return name

parentPath = path.parent()
while parentPath is not None :
if isinstance( column.inspector( parentPath ), GafferSceneUI.Private.AttributeInspector ) :
# The name of the first AttributeInspector ancestor of the parameter is the shader attribute
## \todo Could we instead query this from the ParameterInspector?
with context :
network = scene.fullAttributes( context["scene:path"] ).get( parentPath[-1], None )
if isinstance( network, IECoreScene.ShaderNetwork ) and network.getOutput().shader != parameter.shader :
name = f"{parameter.shader}.{parameter.name}"
break

parentPath = parentPath.parent()

return name

def _updateFromContext( self, modifiedItems ) :

self.__lazyUpdateFromContexts()
Expand Down
41 changes: 30 additions & 11 deletions python/GafferSceneUI/ShaderTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,9 @@ def __addTweak( self, name, plugTypeOrValue ) :

def __dropData( self, event ) :

if isinstance( event.data, Gaffer.ValuePlug ) :
if event.sourceWidget.ancestor( GafferSceneUI.SceneInspector ) is not None :
return "", GafferSceneUI.SceneInspector.draggedParameters( event )
elif isinstance( event.data, Gaffer.ValuePlug ) :
plug = event.data
if (
Gaffer.PlugAlgo.canSetValueFromData( plug ) or
Expand All @@ -349,7 +351,7 @@ def __dropData( self, event ) :
name = plug.getName() if plug.direction() == Gaffer.Plug.Direction.In else ""
return name, plug
elif isinstance( event.data, IECore.Data ) :
return "", event.data
return "", event.data
elif isinstance( event.data, IECore.ObjectMatrix ) :
matrix = event.data
if (
Expand Down Expand Up @@ -381,6 +383,25 @@ def __drop( self, widget, event ) :
name, plugOrData = self.__dropData( event )
assert( plugOrData is not None )

warning = ""
with Gaffer.UndoScope( self.scriptNode() ) :
if name == "" and isinstance( plugOrData, dict ) :
for tweakName, tweakValue in plugOrData.items() :
w = self.__createTweakFromPlugOrData( tweakName, tweakValue )
if w != "" :
if warning != "" :
warning += "<br>"
warning += f"{tweakName} : {w}"
else :
warning = self.__createTweakFromPlugOrData( name, plugOrData )

if warning != "" :
GafferUI.PopupWindow.showWarning( warning, parent = self )

return True

def __createTweakFromPlugOrData( self, name, plugOrData ) :

inputPlug = None
if isinstance( plugOrData, Gaffer.Plug ) :
valuePlug = plugOrData.createCounterpart( "value", Gaffer.Plug.Direction.In )
Expand All @@ -390,8 +411,7 @@ def __drop( self, widget, event ) :
try :
valuePlug = Gaffer.PlugAlgo.createPlugFromData( "value", Gaffer.Plug.Direction.In, Gaffer.Plug.Flags.Default, plugOrData )
except :
GafferUI.PopupWindow.showWarning( "Unsupported data type", parent = self )
return True
return "Unsupported data type"

tweakPlug = Gaffer.TweakPlug(
name, valuePlug.createCounterpart( "value", Gaffer.Plug.Direction.In ),
Expand All @@ -404,14 +424,13 @@ def __drop( self, widget, event ) :
# default to `Create` mode.
tweakPlug["mode"].setValue( tweakPlug.Mode.Create )

with Gaffer.UndoScope( self.scriptNode() ) :
self.getPlug().addChild( tweakPlug )
if inputPlug is not None :
tweakPlug["value"].setInput( inputPlug )
if not isinstance( tweakPlug["value"], GafferScene.ClosurePlug ) :
Gaffer.Metadata.registerValue( tweakPlug, "noduleLayout:visible", True )
self.getPlug().addChild( tweakPlug )
if inputPlug is not None :
tweakPlug["value"].setInput( inputPlug )
if not isinstance( tweakPlug["value"], GafferScene.ClosurePlug ) :
Gaffer.Metadata.registerValue( tweakPlug, "noduleLayout:visible", True )

return True
return ""

class _ShaderTweakPlugValueWidget( GafferUI.TweakPlugValueWidget ) :

Expand Down
Loading