Skip to content

Commit 4b6c116

Browse files
committed
Open usdview without specifying a file
Signed-off-by: Divyansh Mishra <[email protected]>
1 parent ad5d719 commit 4b6c116

File tree

2 files changed

+46
-15
lines changed

2 files changed

+46
-15
lines changed

pxr/usdImaging/usdviewq/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ def RegisterPositionals(self, parser):
9797
register positional arguments on the ArgParser
9898
'''
9999
parser.add_argument('usdFile', action='store',
100+
nargs='?',
100101
type=str,
101-
help='The file to view')
102+
help='The file to view (Optional)')
102103

103104
def RegisterOptions(self, parser):
104105
'''
@@ -344,11 +345,16 @@ def GetResolverContext(self, usdFile):
344345
context is provided. For usdview, configuring an asset context by
345346
default is reasonable, and allows clients that embed usdview to
346347
achieve different behavior when needed.
348+
349+
If usdFile is None (Falsy value), a default context will be created.
347350
"""
348351
from pxr import Ar
349352

350353
r = Ar.GetResolver()
351354

355+
if not usdFile:
356+
return r.CreateDefaultContext()
357+
352358
# ConfigureResolverForAsset no longer exists under Ar 2.0; this
353359
# is here for backwards compatibility with Ar 1.0.
354360
if hasattr(r, "ConfigureResolverForAsset"):

pxr/usdImaging/usdviewq/appController.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ def __init__(self, parserData, resolverContextFn):
402402
self._ui = Ui_MainWindow()
403403
self._ui.setupUi(self._mainWindow)
404404

405-
self._mainWindow.setWindowTitle(parserData.usdFile)
405+
self._mainWindow.setWindowTitle(parserData.usdFile or "Empty Stage")
406406
self._statusBar = QtWidgets.QStatusBar(self._mainWindow)
407407
self._mainWindow.setStatusBar(self._statusBar)
408408

@@ -1200,22 +1200,30 @@ def _MuteMatchingLayers():
12001200
# second pass in order to mute additional
12011201
# layers populated after loading
12021202
_MuteMatchingLayers()
1203-
1204-
def _openStage(self, usdFilePath, sessionFilePath,
1205-
populationMaskPaths, muteLayersRe):
1203+
1204+
def _getEmptyStage(self):
1205+
1206+
with self._makeTimer('create empty stage'):
1207+
sessionLayer = Sdf.Layer.CreateAnonymous()
1208+
stage = Usd.Stage.CreateInMemory('Empty Stage', sessionLayer, self._resolverContextFn(None))
1209+
1210+
if not stage:
1211+
sys.stderr.write('Error: Unable to create empty stage\n')
1212+
return stage
1213+
1214+
def _getStageForFile(self, usdFilePath, sessionFilePath,
1215+
populationMaskPaths, muteLayersRe):
12061216

12071217
def _GetFormattedError(reasons=None):
12081218
err = ("Error: Unable to open stage '{0}'\n".format(usdFilePath))
12091219
if reasons:
12101220
err += "\n".join(reasons) + "\n"
12111221
return err
1212-
1222+
12131223
if not Ar.GetResolver().Resolve(usdFilePath):
12141224
sys.stderr.write(_GetFormattedError(["File not found"]))
12151225
sys.exit(1)
12161226

1217-
if self._mallocTags != 'none':
1218-
Tf.MallocTag.Initialize()
12191227

12201228
with self._makeTimer('open stage "%s"' % usdFilePath):
12211229
loadSet = Usd.Stage.LoadNone if (self._unloaded or muteLayersRe) \
@@ -1262,8 +1270,22 @@ def _GetFormattedError(reasons=None):
12621270

12631271
if not stage:
12641272
sys.stderr.write(_GetFormattedError())
1273+
return stage
1274+
1275+
def _openStage(self, usdFilePath, sessionFilePath,
1276+
populationMaskPaths, muteLayersRe):
1277+
1278+
if self._mallocTags != 'none':
1279+
Tf.MallocTag.Initialize()
1280+
1281+
if not usdFilePath:
1282+
stage = self._getEmptyStage()
1283+
12651284
else:
1266-
stage.SetEditTarget(stage.GetSessionLayer())
1285+
stage = self._getStageForFile(usdFilePath, sessionFilePath,
1286+
populationMaskPaths, muteLayersRe)
1287+
1288+
stage.SetEditTarget(stage.GetSessionLayer())
12671289

12681290
if self._mallocTags == 'stage':
12691291
DumpMallocTags(stage, "stage-loading")
@@ -2804,9 +2826,13 @@ def _getSaveFileName(self, caption, recommendedFilename):
28042826

28052827
return saveName
28062828

2829+
def _getRecommendedFilenamePrefix(self):
2830+
return (self._parserData.usdFile.rsplit('.', 1)[0]
2831+
if self._parserData.usdFile
2832+
else 'new_file')
2833+
28072834
def _saveOverridesAs(self):
2808-
recommendedFilename = self._parserData.usdFile.rsplit('.', 1)[0]
2809-
recommendedFilename += '_overrides.usd'
2835+
recommendedFilename = self._getRecommendedFilenamePrefix() + '_overrides.usd'
28102836

28112837
saveName = self._getSaveFileName(
28122838
'Save Overrides As', recommendedFilename)
@@ -2830,7 +2856,7 @@ def _saveOverridesAs(self):
28302856
# in which case it would create an in-memory root layer, to which
28312857
# all edits will be targeted. In order to future proof
28322858
# this, first fetch the root layer, and if it is anonymous, just
2833-
# export it to the given filename. If it isn't anonmyous (i.e., it
2859+
# export it to the given filename. If it isn't anonymous (i.e., it
28342860
# is a regular usd file on disk), export the session layer and add
28352861
# the stage root file as a sublayer.
28362862
rootLayer = self._dataModel.stage.GetRootLayer()
@@ -2858,8 +2884,7 @@ def _saveOverridesAs(self):
28582884
saveName, 'Created by UsdView')
28592885

28602886
def _saveFlattenedAs(self):
2861-
recommendedFilename = self._parserData.usdFile.rsplit('.', 1)[0]
2862-
recommendedFilename += '_flattened.usd'
2887+
recommendedFilename = self._getRecommendedFilenamePrefix() + '_flattened.usd'
28632888

28642889
saveName = self._getSaveFileName(
28652890
'Save Flattened As', recommendedFilename)
@@ -2874,7 +2899,7 @@ def _copyViewerImage(self):
28742899

28752900
def _saveViewerImage(self):
28762901
recommendedFilename = "{}_{}{:04d}.png".format(
2877-
self._parserData.usdFile.rsplit('.', 1)[0],
2902+
self._getRecommendedFilenamePrefix(),
28782903
"" if not self.getActiveCamera()
28792904
else self.getActiveCamera().GetName() + "_",
28802905
int(self._dataModel.currentFrame.GetValue()))

0 commit comments

Comments
 (0)