Add a --vars argument to usdrecord, allowing expression variables
authorblevin <blevin@users.noreply.github.com>
Sat, 3 Feb 2024 03:24:31 +0000 (19:24 -0800)
committerpixar-oss <pixar-oss@users.noreply.github.com>
Sat, 3 Feb 2024 03:24:31 +0000 (19:24 -0800)
to be specified on the command line.  They will be set on the session
layer before recording.

(Internal change: 2313259)

pxr/usdImaging/bin/usdrecord/CMakeLists.txt
pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/baseline/out.png [new file with mode: 0644]
pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/grid.tex [new file with mode: 0644]
pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/textureCard.usda [new file with mode: 0644]
pxr/usdImaging/bin/usdrecord/usdrecord.py

index aac1c4e74d6d8688ecd7223e7b1eeb7b10df65df..33910e3925fb7e7c77a304bd15b953258b9c4241 100644 (file)
@@ -29,6 +29,11 @@ pxr_install_test_dir(
     DEST testUsdRecordSmallObject
 )
 
+pxr_install_test_dir(
+    SRC testenv/ExpressionVariableTest
+    DEST testUsdRecordExpressionTest
+)
+
 if (NOT PXR_HEADLESS_TEST_MODE)
 
     pxr_register_test(testUsdRecordSingleFrame
@@ -49,4 +54,10 @@ if (NOT PXR_HEADLESS_TEST_MODE)
         EXPECTED_RETURN_CODE 0
     )
 
+    pxr_register_test(testUsdRecordExpressionVariable
+        PYTHON
+        COMMAND "${CMAKE_INSTALL_PREFIX}/bin/usdrecord textureCard.usda out.png --vars TEXTURE=grid"
+        EXPECTED_RETURN_CODE 0
+    )
+
 endif()
diff --git a/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/baseline/out.png b/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/baseline/out.png
new file mode 100644 (file)
index 0000000..3a750d3
Binary files /dev/null and b/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/baseline/out.png differ
diff --git a/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/grid.tex b/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/grid.tex
new file mode 100644 (file)
index 0000000..d774776
Binary files /dev/null and b/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/grid.tex differ
diff --git a/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/textureCard.usda b/pxr/usdImaging/bin/usdrecord/testenv/ExpressionVariableTest/textureCard.usda
new file mode 100644 (file)
index 0000000..6e4f777
--- /dev/null
@@ -0,0 +1,64 @@
+#usda 1.0
+(
+    upAxis = "Y"
+    '''This file is used to demonstrate how expression variables can be passed to usdrecord
+    on the command-line.  It will set them on the stage's session layer, allowing them to
+    be used in asset-valued attribute resolution.
+
+    In this file, the variable ${TEXTURE} is used to indicate a texture filename.'''
+)
+
+def Mesh "card" (
+    prepend apiSchemas = ["MaterialBindingAPI"]
+)
+{
+    rel material:binding = </PreviewMaterial>
+
+    point3f[] points = [
+        (0, 0, 0),
+        (1, 0, 0),
+        (0, 1, 0),
+        (1, 1, 0),
+    ]
+    float2[] primvars:st (interpolation = "vertex")
+    float2[] primvars:st = [
+        (0, 0),
+        (1, 0),
+        (0, 1),
+        (1, 1)
+    ]
+    int[] faceVertexIndices = [
+        0, 1, 3, 2
+    ]
+    int[] faceVertexCounts = [
+        4
+    ]
+    uniform token subdivisionScheme = "none"
+}
+
+def Material "PreviewMaterial"
+{
+    add token outputs:surface.connect = </PreviewMaterial/PreviewSurface.outputs:surface>
+
+    def Shader "PreviewSurface"
+    {
+        token info:id = "UsdPreviewSurface"
+        color3f inputs:emissiveColor.connect = </PreviewMaterial/ColorAndOpacityTexture.outputs:rgb>
+        token outputs:surface
+    }
+
+    def Shader "UV"
+    {
+        token info:id = "UsdPrimvarReader_float2"
+        string inputs:varname = "st"
+        float2 outputs:result
+    }
+
+    def Shader "ColorAndOpacityTexture"
+    {
+        token info:id = "UsdUVTexture"
+        asset inputs:file = @`"${TEXTURE}.tex"`@
+        float2 inputs:st.connect = </PreviewMaterial/UV.outputs:result>
+        color3f outputs:rgb
+    }
+}
index 631c0b6942e6f258211d72dc6b4382aa656eb891..5b99f8a9cc23f37bba397dc9de025a278d12b8d2 100644 (file)
@@ -24,6 +24,7 @@
 #
 
 from pxr import Usd
+from pxr import Sdf
 from pxr import UsdAppUtils
 from pxr import Tf
 
@@ -126,6 +127,13 @@ def main():
             'more than one extra purpose, either use commas with no spaces or '
             'quote the argument and separate purposes by commas and/or spaces.'))
 
+    parser.add_argument('--vars', action='store', type=str, nargs='*',
+        dest='expressionVariables', metavar='NAME=VALUE',
+        help=(
+            'Specify expression variables and their values to override in '
+            'a session layer.  Currently, only string-valued variables '
+            'are supported.'))
+
     # Note: The argument passed via the command line (disableGpu) is inverted
     # from the variable in which it is stored (gpuEnabled).
     parser.add_argument('--disableGpu', action='store_false',
@@ -167,6 +175,22 @@ def main():
 
     purposes = args.purposes.replace(',', ' ').split()
 
+    # Prepare a session layer with requested expressionVariables
+    sessionLayer = Sdf.Layer.CreateAnonymous("usdrecord-session.usda",
+        {Sdf.FileFormat.Tokens.TargetArg: Usd.UsdFileFormat.Tokens.Target})
+    if args.expressionVariables:
+        exprVars = sessionLayer.expressionVariables
+        for entry in args.expressionVariables:
+            name, val = entry.split('=')
+            exprVars[name] = val
+        sessionLayer.expressionVariables = exprVars
+
+    # Load the root layer.
+    rootLayer = Sdf.Layer.FindOrOpen(args.usdFilePath)
+    if not rootLayer:
+        _Err('Could not open layer: %s' % args.usdFilePath)
+        return 1
+
     # Open the USD stage, using a population mask if paths were given.
     if args.populationMask:
         populationMaskPaths = args.populationMask.replace(',', ' ').split()
@@ -175,9 +199,9 @@ def main():
         for maskPath in populationMaskPaths:
             populationMask.Add(maskPath)
 
-        usdStage = Usd.Stage.OpenMasked(args.usdFilePath, populationMask)
+        usdStage = Usd.Stage.OpenMasked(rootLayer, sessionLayer, populationMask)
     else:
-        usdStage = Usd.Stage.Open(args.usdFilePath)
+        usdStage = Usd.Stage.Open(rootLayer, sessionLayer)
 
     if not usdStage:
         _Err('Could not open USD stage: %s' % args.usdFilePath)