Skip to content

Commit

Permalink
EditScopeUI : Added summaries of edits in NodeEditor
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhaddon committed Apr 2, 2024
1 parent 06c0985 commit c58f1ed
Show file tree
Hide file tree
Showing 3 changed files with 388 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Features
- USD Kind : When selecting, the first ancestor location with a `usd:kind` attribute matching the chosen list of USD Kind will ultimately be selected. USD's Kind Registry includes `Assembly`, `Component`, `Group`, `Model` and `SubComponent` by default and can be extended via USD startup scripts.
- Shader Assignment : When selecting, the first ancestor location with a renderable and direct (not inherited) shader attribute will ultimately be selected. This can be used to select either surface or displacement shaders.

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

- EditScope : Added a summary of edits in the NodeEditor, with the ability to select the affected objects and quickly navigate to the processor nodes.

Fixes
-----

Expand All @@ -21,6 +26,9 @@ API
---

- SelectionTool : Added static `registerSelectMode()` method for registering a Python or C++ function that will modify a selected scene path location. Users can choose which mode is active when selecting.
- EditScopeUI : Added an API for customising the EditScope's NodeEditor with summaries for each processor :
- ProcessorWidget provides a base class for custom widgets, and a factory mechanism for registering them against processors.
- SimpleProcessorWidget provides a base class for widgets with a simple summary label and optional action links.

1.4.0.0b5 (relative to 1.4.0.0b4)
=========
Expand Down
149 changes: 149 additions & 0 deletions python/GafferSceneUI/EditScopeUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
import GafferScene
import GafferSceneUI

# Pruning/Visibility hotkeys
# ==========================

def addPruningActions( editor ) :

if isinstance( editor, GafferUI.Viewer ) :
Expand Down Expand Up @@ -154,3 +157,149 @@ def __visibilityKeyPress( viewer, event ) :
tweakPlug["value"].setValue( False )

return True


# Processor Widgets
# =================

class _SceneProcessorWidget( GafferUI.EditScopeUI.SimpleProcessorWidget ) :

def _linkActivated( self, linkData ) :

GafferSceneUI.ContextAlgo.setSelectedPaths(
self.processor().ancestor( Gaffer.ScriptNode ).context(), linkData
)

class __LocationEditsWidget( _SceneProcessorWidget ) :

@staticmethod
def _summary( processor, linkCreator ) :

# Get the locations being edited from the spreadsheet.

canceller = Gaffer.Context.current().canceller()
activePathMatcher = IECore.PathMatcher()
disabledPathMatcher = IECore.PathMatcher()
for row in processor["edits"] :
IECore.Canceller.check( canceller )
path = row["name"].getValue()
if not path :
continue
if row["enabled"].getValue() :
activePathMatcher.addPath( path )
else :
disabledPathMatcher.addPath( path )

# Match those against the scene.

activePaths = IECore.PathMatcher()
disabledPaths = IECore.PathMatcher()
GafferScene.SceneAlgo.matchingPaths( activePathMatcher, processor["in"], activePaths )
GafferScene.SceneAlgo.matchingPaths( disabledPathMatcher, processor["in"], disabledPaths )

# Build a summary describing what we found.

summaries = []
if activePaths.size() :
activeLink = linkCreator(
"{} location{}".format( activePaths.size(), "s" if activePaths.size() > 1 else "" ),
activePaths
)
summaries.append( f"edits on {activeLink}" )
if disabledPaths.size() :
disabledLink = linkCreator(
"{} location{}".format( disabledPaths.size(), "s" if disabledPaths.size() > 1 else "" ),
disabledPaths
)
summaries.append( f"disabled edits on {disabledLink}" )

if not summaries :
return "None"

summaries[0] = summaries[0][0].upper() + summaries[0][1:]
return " and ".join( summaries )

GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "AttributeEdits TransformEdits *LightEdits *SurfaceEdits", __LocationEditsWidget )

class __PruningEditsWidget( _SceneProcessorWidget ) :

@staticmethod
def _summary( processor, linkCreator ) :

paths = IECore.PathMatcher()
GafferScene.SceneAlgo.matchingPaths( processor["PathFilter"], processor["in"], paths )

if paths.isEmpty() :
return "None"
else :
link = linkCreator(
"{} location{}".format( paths.size(), "s" if paths.size() > 1 else "" ),
paths
)
return f"{link} pruned"

GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "PruningEdits", __PruningEditsWidget )

class __RenderPassesWidget( GafferUI.EditScopeUI.SimpleProcessorWidget ) :

@staticmethod
def _summary( processor, linkCreator ) :

names = processor["names"].getValue()
return "{} render pass{} created".format(
len( names ) if names else "No",
"es" if len( names ) > 1 else "",
)

GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "RenderPasses", __RenderPassesWidget )

class __RenderPassOptionEditsWidget( GafferUI.EditScopeUI.SimpleProcessorWidget ) :

@staticmethod
def _summary( processor, linkCreator ) :

enabledOptions = set()
enabledPasses = set()
disabledPasses = set()
for row in processor["edits"].children()[1:] :
renderPass = row["name"].getValue()
if not renderPass :
continue
if not row["enabled"].getValue() :
disabledPasses.add( renderPass )
continue

passEnabledOptions = {
cell["value"]["name"].getValue()
for cell in row["cells"]
if cell["value"]["enabled"].getValue()
}

if passEnabledOptions :
enabledPasses.add( renderPass )
enabledOptions = enabledOptions | passEnabledOptions

summaries = []
if enabledOptions :
summaries.append(
"edits to {} option{} in {} render pass{}".format(
len( enabledOptions ), "s" if len( enabledOptions ) > 1 else "",
len( enabledPasses ), "es" if len( enabledPasses ) > 1 else "",
)
)

if disabledPasses :
summaries.append(
"disabled edits for {} render pass{}".format(
len( disabledPasses ), "es" if len( disabledPasses ) > 1 else ""
)
)

if not summaries :
return "None"

summaries[0] = summaries[0][0].upper() + summaries[0][1:]
return " and ".join( summaries )


GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "RenderPassOptionEdits", __RenderPassOptionEditsWidget )
Loading

0 comments on commit c58f1ed

Please sign in to comment.