When using the UsdPayloads list‑editing API (RemovePayload, SetPayloads) in an override layer, the original payload from a lower reference isn’t removed—both payloads remain active in the final composed stage.
Documentation:
LayerStack: a stack of layers that compose a USD stage:
I’m using SetPayloads function which should explicitly replace the payload at the /Scene/payloadA prim. Even force-deleting the payload from a lower comp arc in the layer stack doesn’t seem to work.
How to Reproduce
I’ve attached this reproduction python script will create 5 usda files in the same folder you run it in. I’ve been viewing the resulting stage of Main.usda in usdview. I’m on USD version 24.8.
Any assistance in confirming this bug or finding a workaround would be greatly appreciated.
Best,
–Felipe
from pxr import Usd, UsdGeom, Sdf
# 1. Create PayloadA_ORIG.usda
payloadAStage = Usd.Stage.CreateNew('PayloadA_ORIG.usda') # Create new stage
payloadARoot = UsdGeom.Xform.Define(payloadAStage, '/payloadA') # Define default prim path
payloadAStage.SetDefaultPrim(payloadARoot.GetPrim()) # Set defaultPrim = "payloadA"
UsdGeom.Xform.Define(payloadAStage, '/payloadA/payloadA1_1')
UsdGeom.Xform.Define(payloadAStage, '/payloadA/payloadA1_2')
payloadAStage.GetRootLayer().Save()
# 2. Create PayloadA_NEW.usda
newPayloadAStage = Usd.Stage.CreateNew('PayloadA_NEW.usda') # Create new stage
newPayloadARoot = UsdGeom.Xform.Define(newPayloadAStage, '/payloadA') # Define default prim path
newPayloadAStage.SetDefaultPrim(newPayloadARoot.GetPrim()) # Set defaultPrim = "payloadA"
UsdGeom.Xform.Define(newPayloadAStage, '/payloadA/new_payloadA1')
UsdGeom.Xform.Define(newPayloadAStage, '/payloadA/new_payloadA2')
UsdGeom.Xform.Define(newPayloadAStage, '/payloadA/new_payloadA3')
newPayloadAStage.GetRootLayer().Save()
# 3. Create BaseLayer.usda
baseStage = Usd.Stage.CreateNew('BaseLayer.usda') # Create new stage
baseSceneXform = UsdGeom.Xform.Define(baseStage, '/Scene')
basePayloadXform = UsdGeom.Xform.Define(baseStage, '/Scene/payloadA')
basePayloadPrim = baseSceneXform.GetPrim()
payloadPrim = basePayloadXform.GetPrim()
baseStage.SetDefaultPrim(basePayloadPrim) # Set defaultPrim = "Scene"
basePayload = Sdf.Payload('PayloadA_ORIG.usda')
payloadPrim.GetPayloads().SetPayloads([basePayload]) # Append payload listOp
baseStage.GetRootLayer().Save()
# 4. Create Override.usda
overrideStage = Usd.Stage.CreateNew('Override.usda')
overrideSceneXform = UsdGeom.Xform.Define(overrideStage, '/Scene')
overridePayloadXform = UsdGeom.Xform.Define(overrideStage, '/Scene/payloadA')
overrideScenePrim = overrideSceneXform.GetPrim()
overridePayloadPrim = overridePayloadXform.GetPrim()
overrideStage.SetDefaultPrim(overrideScenePrim) # Set defaultPrim = "Scene"
payloadsAPI = overridePayloadPrim.GetPayloads()
# This call doesn't seem to do anything or create any errors even if you specify a target layer.
payloadsAPI.RemovePayload(Sdf.Payload('PayloadA_ORIG.usda'))
# Set SetPayloads instead of AddPayloads
payloadsAPI.SetPayloads([Sdf.Payload('PayloadA_NEW.usda')])
overrideStage.GetRootLayer().Save()
# 5. Create Main.usda
mainStage = Usd.Stage.CreateNew('Main.usda')
sceneXform = UsdGeom.Xform.Define(mainStage, '/Scene')
scenePrim = sceneXform.GetPrim()
scenePrim.GetReferences().AddReference(
assetPath='BaseLayer.usda',
primPath=Sdf.Path() # reference the defaultPrim of that layer
)
# Set subLayers listOp
mainStage.GetRootLayer().subLayerPaths = ['Override.usda']
mainStage.GetRootLayer().Save()
def forciblyDeletePayload():
filePath = 'Override.usda'
# 1. Read all lines
with open(filePath, 'r') as f:
lines = f.readlines()
# 2. Find the index of the NEW-payload line
targetIndex = None
for i, line in enumerate(lines):
if 'payload = @PayloadA_NEW.usda@' in line:
targetIndex = i
break
if targetIndex is None:
raise RuntimeError("Couldn't find the NEW-payload line in Override.usda")
# 3. Compute indentation and build insert lines
indentation = lines[targetIndex][:len(lines[targetIndex]) - len(lines[targetIndex].lstrip())]
commentLine = f"{indentation}delete payload = @PayloadA_ORIG.usda@\n"
# 4. Insert them just before the NEW-payload line
lines.insert(targetIndex, commentLine)
# 5. Write back out
with open(filePath, 'w') as f:
f.writelines(lines)
# forciblyDeletePayload() # Comment this in to forcebly add the "delete payload = @PayloadA_ORIG.usda@" line
print(f"Usd Version: {Usd.GetVersion()[1]}.{Usd.GetVersion()[2]}")
Would you be able to file an issue against the OpenUSD repo with the contents of your post? It’ll help just officially track it at the very least as something that’s being hit.