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: 7 additions & 1 deletion pxr/usdImaging/usdviewq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ def RegisterPositionals(self, parser):
register positional arguments on the ArgParser
'''
parser.add_argument('usdFile', action='store',
nargs='?',
type=str,
help='The file to view')
help='The file to view (Optional)')

def RegisterOptions(self, parser):
'''
Expand Down Expand Up @@ -372,10 +373,15 @@ def GetResolverContext(self, usdFile):
context is provided. For usdview, configuring an asset context by
default is reasonable, and allows clients that embed usdview to
achieve different behavior when needed.

If usdFile path is not provided, it returns default context.
"""
from pxr import Ar

r = Ar.GetResolver()

if not usdFile:
return r.CreateDefaultContext()

# ConfigureResolverForAsset no longer exists under Ar 2.0; this
# is here for backwards compatibility with Ar 1.0.
Expand Down
62 changes: 47 additions & 15 deletions pxr/usdImaging/usdviewq/appController.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def __init__(self, parserData, resolverContextFn):
self._ui = Ui_MainWindow()
self._ui.setupUi(self._mainWindow)

self._mainWindow.setWindowTitle(parserData.usdFile)
self._mainWindow.setWindowTitle(parserData.usdFile or "Empty Stage")
self._statusBar = QtWidgets.QStatusBar(self._mainWindow)
self._mainWindow.setStatusBar(self._statusBar)

Expand Down Expand Up @@ -1203,7 +1203,16 @@ def _MuteMatchingLayers():
# layers populated after loading
_MuteMatchingLayers()

def _openStage(self, usdFilePath, sessionFilePath,
def _getEmptyStage(self):

with self._makeTimer('create empty stage'):
stage = Usd.Stage.CreateInMemory()

if not stage:
sys.stderr.write('Error: Unable to create empty stage\n')
return stage

def _getStageForFile(self, usdFilePath, sessionFilePath,
populationMaskPaths, muteLayersRe):

def _GetFormattedError(reasons=None):
Expand Down Expand Up @@ -1281,6 +1290,25 @@ def _GetFormattedError(reasons=None):

return stage

def _openStage(self, usdFilePath, sessionFilePath,
populationMaskPaths, muteLayersRe):

if self._mallocTags != 'none':
Tf.MallocTag.Initialize()

if not usdFilePath:
stage = self._getEmptyStage()

else:
stage = self._getStageForFile(usdFilePath, sessionFilePath,
populationMaskPaths, muteLayersRe)
stage.SetEditTarget(stage.GetSessionLayer())

if self._mallocTags == 'stage':
DumpMallocTags(stage, "stage-loading")

return stage

Comment on lines +1293 to +1311
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this PR is missing a lot of logic from the _openStage method, perhaps a bad merge? -

def _openStage(self, usdFilePath, sessionFilePath,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment!

I renamed the old _openStage function to _getStageForFile and now the _openStage calls _getStageForFile or _getEmptyStage based on whether usdFile was passed as an argument. This way the callers of _openStage are unaffected.

Please let me know if there are any other concerns.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh sorry, missed that. thanks!

def _closeStage(self):
# Close the USD stage.
if self._stageView:
Expand Down Expand Up @@ -2795,6 +2823,12 @@ def _cleanAndClose(self):

# Start timer to measure Qt shutdown time
self._startQtShutdownTimer()


def _getRecommendedFilenamePrefix(self):
return (self._parserData.usdFile.rsplit('.', 1)[0]
if self._parserData.usdFile
else 'new_file')

def _openFile(self):
extensions = Sdf.FileFormat.FindAllFileFormatExtensions()
Expand Down Expand Up @@ -2836,14 +2870,13 @@ def _getSaveFileName(self, caption, recommendedFilename):
return saveName

def _saveOverridesAs(self):
recommendedFilename = self._parserData.usdFile.rsplit('.', 1)[0]
recommendedFilename += '_overrides.usd'
recommendedFilename = self._getRecommendedFilenamePrefix() + '_overrides.usd'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below at os.path.samefile(saveName, self._parserData.usdFile):

With an empty stage, if we want to save overrides to an existing file, self._parserData.usdFile will be None and an error occurs.


saveName = self._getSaveFileName(
'Save Overrides As', recommendedFilename)
if len(saveName) == 0:
return
elif (os.path.isfile(saveName) and
elif (os.path.isfile(saveName) and self._parserData.usdFile and
os.path.samefile(saveName, self._parserData.usdFile)):
msg = QtWidgets.QMessageBox()
msg.setIcon(QtWidgets.QMessageBox.Critical)
Expand All @@ -2857,13 +2890,13 @@ def _saveOverridesAs(self):
return

with BusyContext():
# In the future, we may allow usdview to be brought up with no file,
# in which case it would create an in-memory root layer, to which
# all edits will be targeted. In order to future proof
# this, first fetch the root layer, and if it is anonymous, just
# export it to the given filename. If it isn't anonmyous (i.e., it
# is a regular usd file on disk), export the session layer and add
# the stage root file as a sublayer.
# usdview can be brought up with no file, in which case it
# creates an in-memory root layer, to which all edits are
# targeted. This first fetches the root layer, and if it is
# anonymous, just exports it to the given filename. If it
# isn't anonymous (i.e., it is a regular usd file on disk),
# exports the session layer and add the stage root file
# as a sublayer.
rootLayer = self._dataModel.stage.GetRootLayer()
if not rootLayer.anonymous:
self._dataModel.stage.GetSessionLayer().Export(
Expand All @@ -2889,8 +2922,7 @@ def _saveOverridesAs(self):
saveName, 'Created by UsdView')

def _saveFlattenedAs(self):
recommendedFilename = self._parserData.usdFile.rsplit('.', 1)[0]
recommendedFilename += '_flattened.usd'
recommendedFilename = self._getRecommendedFilenamePrefix() + '_flattened.usd'

saveName = self._getSaveFileName(
'Save Flattened As', recommendedFilename)
Expand All @@ -2905,7 +2937,7 @@ def _copyViewerImage(self):

def _saveViewerImage(self):
recommendedFilename = "{}_{}{:04d}.png".format(
self._parserData.usdFile.rsplit('.', 1)[0],
self._getRecommendedFilenamePrefix(),
"" if not self.getActiveCamera()
else self.getActiveCamera().GetName() + "_",
int(self._dataModel.currentFrame.GetValue()))
Expand Down