Hello,
Is there a way to undo only current viewport navigation like we do with “Alt+Z” in Softimage ?
Thanks
Undo for viewport navigation ?
19376 25 5- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- anon_user_89151269
- Member
- 1755 posts
- Joined: 3月 2014
- Offline
Exactly this behavior no, but there's something one can do to emulate that:
navigate your viewport through a locked camera (3rd lock icon on the tool bar on the right side of the viewport).
Of course it's rather limited for an “in the now” usage so to speak, since the undo will fill with other actions as you work and you won't be able to undo your camera changes.
File a RFE for “separate camera undo/redo stack” if you miss this feature so much.
navigate your viewport through a locked camera (3rd lock icon on the tool bar on the right side of the viewport).
Of course it's rather limited for an “in the now” usage so to speak, since the undo will fill with other actions as you work and you won't be able to undo your camera changes.
File a RFE for “separate camera undo/redo stack” if you miss this feature so much.
Edited by anon_user_89151269 - 2018年6月27日 06:14:47
- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- Grendizer
- Member
- 375 posts
- Joined: 5月 2014
- Offline
- Rebus B
- Member
- 80 posts
- Joined: 6月 2013
- Offline
- Rebus B
- Member
- 80 posts
- Joined: 6月 2013
- Offline
- Grendizer
- Member
- 375 posts
- Joined: 5月 2014
- Offline
- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- Control_Vertex
- Member
- 162 posts
- Joined: 5月 2015
- Offline
- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- OneBigTree
- Member
- 382 posts
- Joined: 11月 2010
- Offline
- julca
- Member
- 219 posts
- Joined: 10月 2015
- Offline
- Grendizer
- Member
- 375 posts
- Joined: 5月 2014
- Offline
- Control_Vertex
- Member
- 162 posts
- Joined: 5月 2015
- Offline
- anon_user_89151269
- Member
- 1755 posts
- Joined: 3月 2014
- Offline
As I said in another thread, it's best to make a habit of keying your camera. It's a solution for both the present and it would still be a good idea to do it even if you were to have this feature implemented, if the goal is to make sure you don't lose your camera transformation. And make sure “auto-commit changes” is off, or you'll update the keys every time you modify the cam view.
Edited by anon_user_89151269 - 2019年4月11日 12:58:34
- motionpunk
- Member
- 14 posts
- Joined: 12月 2016
- Offline
- animatrix_
- Member
- 4729 posts
- Joined: 2月 2012
- Offline
I implemented this recently. You can give it a try. It supports multiple viewports. It has to be installed as a package or can be run without a package by installing directly into Houdini user directory. There seems to be some focus bug about scene viewer only hotkeys so I had to use a global hotkey for these. I will see if it's a bug in Houdini.
pythonrc.py:
456.py:
Special thanks to Alexey of DM and kosukek of SESI
pythonrc.py:
import hou from hdefereval import executeDeferred from PySide2 import QtCore, QtWidgets, QtGui import shiboken2 debug = False def areIdenticalCameras(cam1, cam2): if cam1.isPerspective() and cam2.isOrthographic(): return False if cam2.isPerspective() and cam1.isOrthographic(): return False if cam1.aperture() != cam2.aperture(): return False if cam1.focalLength() != cam2.focalLength(): return False if cam1.aspectRatio() != cam2.aspectRatio(): return False if cam1.orthoWidth() != cam2.orthoWidth(): return False if cam1.rotation() != cam2.rotation(): return False if cam1.translation() != cam2.translation(): return False if cam1.windowOffset() != cam2.windowOffset(): return False if cam1.windowSize() != cam2.windowSize(): return False return True class SceneViewerEventFilter(QtCore.QObject): SceneViewers = [] Refs = [] def __init__(self, sceneViewer, sceneViewerQt): QtCore.QObject.__init__(self) SceneViewerEventFilter.SceneViewers.append(sceneViewer) SceneViewerEventFilter.Refs.append(self) self.sceneViewer = sceneViewer; self.sceneViewerQt = sceneViewerQt; viewport = self.sceneViewer.curViewport() cam = viewport.defaultCamera().stash() self.views = [cam] self.viewtypes = [viewport.type()] self.viewindex = -1 def eventFilter(self, obj, event): if event.type() == QtCore.QEvent.MouseButtonRelease: pane = hou.ui.paneTabUnderCursor() if pane and pane.type() == hou.paneTabType.SceneViewer: if "view" in pane.currentState(): executeDeferred(self.viewChangedEvent) elif event.type() == QtCore.QEvent.MouseMove: if len(self.views) == 0: viewport = self.sceneViewer.curViewport() cam = viewport.defaultCamera().stash() self.views.append(cam) self.viewtypes.append(viewport.type()) if debug: print ("mouse move") """ elif event.type() == QtCore.QEvent.KeyPress: if event.modifiers() & QtCore.Qt.ShiftModifier: if event.key() == QtCore.Qt.Key_Z: self.undoView() elif event.key() == QtCore.Qt.Key_A: self.redoView() """ return False def viewChangedEvent(self, force=False): viewport = self.sceneViewer.curViewport() cam = viewport.defaultCamera().stash() if force or len(self.views) == 0 or not areIdenticalCameras(cam, self.views[-1]): if self.viewindex != -1: self.views = self.views[: self.viewindex + 1] self.viewtypes = self.viewtypes[: self.viewindex + 1] self.viewindex = -1 self.views.append(cam) self.viewtypes.append(viewport.type()) if debug: print ("VIEW CHANGED: ", len(self.views), viewport.type()) print ("------------------------------------") def undoView(self): if self.viewindex == -1: self.viewindex = len(self.views) - 1 if self.viewindex > 0: self.viewindex -= 1 if debug: print ("undo", self.viewindex) viewport = self.sceneViewer.curViewport() viewport.changeType(self.viewtypes[self.viewindex]) try: viewport.setDefaultCamera(self.views[self.viewindex]) except: pass def redoView(self): if self.viewindex == -1: self.viewindex = len(self.views) - 1 if self.viewindex < len(self.viewtypes) - 1: self.viewindex += 1 if debug: print ("redo", self.viewindex) viewport = self.sceneViewer.curViewport() viewport.changeType(self.viewtypes[self.viewindex]) try: viewport.setDefaultCamera(self.views[self.viewindex]) except: pass @staticmethod def reset(): for ref in SceneViewerEventFilter.Refs: ref.views = [] ref.viewtypes = [] ref.viewindex = -1 # Install event filter if it's not installed yet for each viewport def installEventFilterForCurrentViewport(): pane = hou.ui.paneTabUnderCursor() if pane and pane.type() == hou.paneTabType.SceneViewer: if pane not in SceneViewerEventFilter.SceneViewers: if not hasattr(hou.session, "ViewerEventFilters"): hou.session.ViewerEventFilters = [] app = QtWidgets.QApplication.instance() sceneViewerQt = app.widgetAt(QtGui.QCursor.pos()) if len(sceneViewerQt.children()) == 0: viewerEF = SceneViewerEventFilter(pane, sceneViewerQt) hou.session.ViewerEventFilters.append(viewerEF) sceneViewerQt.installEventFilter(viewerEF) if debug: print ("INSTALL EVENT FILTER: ", pane.name()) def viewportViewTypeChangedCallback(): if not hasattr(hou.session, "AllSceneViewers"): hou.session.AllSceneViewers = [] hou.session.AllSceneViewerTypes = [] desktop = hou.ui.curDesktop() panetabs = desktop.paneTabs() for pane in panetabs: if pane.type() == hou.paneTabType.SceneViewer: if pane not in hou.session.AllSceneViewers: hou.session.AllSceneViewers.append(pane) hou.session.AllSceneViewerTypes.append(pane.curViewport().type()) if debug: print ("SCENE VIEWER ADDED") else: index = hou.session.AllSceneViewers.index(pane) viewtype = pane.curViewport().type() if viewtype != hou.session.AllSceneViewerTypes[index]: svindex = SceneViewerEventFilter.SceneViewers.index(pane) sv = SceneViewerEventFilter.Refs[index] if sv.viewindex == -1: if debug: print ("VIEW TYPE CHANGED ", hou.session.AllSceneViewerTypes[index], viewtype) hou.session.AllSceneViewerTypes[index] = viewtype sv.viewChangedEvent(force=True) hou.ui.addEventLoopCallback(installEventFilterForCurrentViewport) hou.ui.addEventLoopCallback(viewportViewTypeChangedCallback) hou.session.SceneViewerEventFilter = SceneViewerEventFilter
456.py:
hou.session.AllSceneViewers = [] hou.session.AllSceneViewerTypes = [] hou.session.SceneViewerEventFilter.reset()
Special thanks to Alexey of DM and kosukek of SESI
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
- Grendizer
- Member
- 375 posts
- Joined: 5月 2014
- Offline
Wow thanks!
I'd like to install this.
In my "houdini19.0" prefs folder, I added a folder called "packages".
Then if I understand correctly I must put your code into a text file and rename it something as "camundo.json"?
Then I must edit 456.py as you shown.
Then if I want to test it, what's the keyboard shortcut? In Maya it's ALT+Z.
Thanks
I'd like to install this.
In my "houdini19.0" prefs folder, I added a folder called "packages".
Then if I understand correctly I must put your code into a text file and rename it something as "camundo.json"?
Then I must edit 456.py as you shown.
Then if I want to test it, what's the keyboard shortcut? In Maya it's ALT+Z.
Thanks
Houdini gamboler
- animatrix_
- Member
- 4729 posts
- Joined: 2月 2012
- Offline
Hi,
I made a separate zip, it's easier than copy pasting everything here. I am using them as part of my full customization so I separated these for there manually, it should work.
As for hotkeys, normally they were within the event filter code but there seems to be a focus problem in the latest Houdini I tried. I have to investigate this with SESI because it happens with scene viewer restricted hotkeys too.
So for now you have to hold Ctrl+Shift+Alt and click each shelf button to assign global hotkeys for undo and redo until that bug is fixed.
I made a separate zip, it's easier than copy pasting everything here. I am using them as part of my full customization so I separated these for there manually, it should work.
As for hotkeys, normally they were within the event filter code but there seems to be a focus problem in the latest Houdini I tried. I have to investigate this with SESI because it happens with scene viewer restricted hotkeys too.
So for now you have to hold Ctrl+Shift+Alt and click each shelf button to assign global hotkeys for undo and redo until that bug is fixed.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
-
- Quick Links