Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause render hotkey #6104

Open
wants to merge 4 commits into
base: 1.5_maintenance
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Improvements
- PythonEditor, PythonCommand, Expression, UIEditor, OSLCode : Added line numbers to code editors (#6091).
- CyclesOptions : Added `denoiseDevice` plug for configuring the device used for denoising.
- AttributeTweaks : Added tooltips and presets for all attribute values.
- InteractiveRenderer :
- Added <kbd>Esc</kbd> hotkey handling to pause an interactive render. This is in addition to the existing behavior of pausing the image viewer.
- Added <kbd>Ctrl</kbd> + <kbd>\</kbd> hotkey handling to toggle the interactive renderer between paused and running. If the new state is `Running`, the image viewer will also be unpaused.
- Starting or unpausing the render using the viewer control play button will also unpause the image viewer.

Fixes
-----
Expand Down
10 changes: 10 additions & 0 deletions doc/source/Interface/ControlsAndShortcuts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ Duplicate current Catalogue image | {kbd}`Ctrl` + {kbd}`D`
Toggle image comparison | {kbd}`Q`
Toggle wipes | {kbd}`W`

### Interactive Render Viewer ###

> Note :
> For the following controls and shortcuts, the cursor must hover over the Viewer.

Action | Control or shortcut
-------------------------------------|--------------------
Pause active render | {kdb}`Escape`
Toggle render running / paused | {kdb}`Ctrl` + {kbd}`\`

### Crop window tool ###

Action | Control or shortcut
Expand Down
31 changes: 28 additions & 3 deletions python/GafferSceneUI/InteractiveRenderUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,17 @@ def __init__( self, view, **kwargs ) :
with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing = 4 ) :
GafferUI.Spacer( imath.V2i( 1, 1 ), imath.V2i( 1, 1 ) )
self.__label = GafferUI.Label( "Render" )
self.__stateWidget = _StatePlugValueWidget( None )
self.__stateWidget = _StatePlugValueWidget( None, view )
self.__messagesWidget = _MessageSummaryPlugValueWidget( None )

self.__view = view

if isinstance( self.__view["in"], GafferImage.ImagePlug ) :
view.plugDirtiedSignal().connect( Gaffer.WeakMethod( self.__viewPlugDirtied ) )

if isinstance( self.__view, GafferUI.View ) :
self.__view.viewportGadget().keyPressSignal().connect( Gaffer.WeakMethod( self.__keyPress ) )

self.__update()

def __update( self ) :
Expand Down Expand Up @@ -177,15 +180,34 @@ def __viewPlugDirtied( self, plug ) :
def __renderNodePlugDirtied( self, plug ) :

if plug.getName() == "state" :
self.__updateLazily();
self.__updateLazily()

def __keyPress( self, widget, event ) :

if event.key == "Escape" :
renderNode = self._interactiveRenderNode( self.__view )
if renderNode is not None :
statePlug = renderNode["state"].source()
statePlug.setValue( GafferScene.InteractiveRender.State.Paused )
elif event.key == "Backslash" and event.modifiers == event.modifiers.Control :
renderNode = self._interactiveRenderNode( self.__view )
if renderNode is not None :
statePlug = renderNode["state"].source()
state = statePlug.getValue()
if state == GafferScene.InteractiveRender.State.Running :
statePlug.setValue( GafferScene.InteractiveRender.State.Paused )
else :
statePlug.setValue( GafferScene.InteractiveRender.State.Running )
if isinstance( self.__view, GafferImageUI.ImageView ) :
self.__view.imageGadget().setPaused( False )

##########################################################################
# UI for the state plug that allows setting the state through buttons
##########################################################################

class _StatePlugValueWidget( GafferUI.PlugValueWidget ) :

def __init__( self, plug, *args, **kwargs) :
def __init__( self, plug, view = None, *args, **kwargs) :

row = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal )
GafferUI.PlugValueWidget.__init__( self, row, plug )
Expand Down Expand Up @@ -214,6 +236,7 @@ def __init__( self, plug, *args, **kwargs) :
}

self.__state = None
self.__view = view

def _updateFromValues( self, values, exception ) :

Expand All @@ -235,6 +258,8 @@ def __startPauseClicked( self, button ) :
# Not enabling undo here is done so that users won't accidentally restart/stop their renderings.
if state != GafferScene.InteractiveRender.State.Running:
self.getPlug().setValue( GafferScene.InteractiveRender.State.Running )
if isinstance( self.__view, GafferImageUI.ImageView ) :
self.__view.imageGadget().setPaused( False )
else:
self.getPlug().setValue( GafferScene.InteractiveRender.State.Paused )

Expand Down
Loading