Custom USD Layers#
This example plugin creates USD departmentlayers and sublayers for newly created shots.
It also defines the default content of each layer.
When creating custom departmentlayers and sublayers, you can use the Layer Order setting to define the order of these layers.
See the section for Single File Plugins on how to load this example.
# CustomUsdLayers.py
name = "CustomUsdLayers"
classname = "CustomUsdLayers"
class CustomUsdLayers:
def __init__(self, core):
self.core = core
self.version = "v1.0.0"
self.core.registerCallback("onShotCreated", self.onShotCreated, plugin=self)
# check if USD plugin is loaded
usdPlugin = self.core.getPlugin("USD")
if usdPlugin:
# if yes, patch the function
self.applyPatch(usdPlugin)
# register callback in case the USD plugin will be loaded later on
# this is important if the plugin gets loaded later on during the startup or manually by the user
self.core.registerCallback(
"pluginLoaded", self.onPluginLoaded, plugin=self
)
def onPluginLoaded(self, plugin):
# check if the loaded plugin is the USD plugin and if yes apply the patch
if plugin.pluginName == "USD":
self.applyPatch(plugin)
def applyPatch(self, plugin):
# apply the monkeypatches to the functions of the USD plugin
# This makes sure that Prism will not create the default USD layers when a shot gets created
self.core.plugins.monkeyPatch(plugin.api.createDftEntityContainer, lambda: False, self, force=True)
self.core.plugins.monkeyPatch(plugin.api.createLayersAutomatically, lambda: False, self, force=True)
def onShotCreated(self, origin, entity):
# function gets called every time a shot gets created
# check if the USD plugin is loaded
usdPlug = self.core.plugins.getPlugin("USD")
if not usdPlug:
return usdPlug
global Usd
from pxr import Usd
usdApi = usdPlug.api
# create the shot USD container
comment = "my custom USD"
path = usdApi.getNewEntityUsdPath(entity, comment=comment)
stage = usdApi.generateStageWithDefaultContent(entity)
result = usdApi.saveStage(stage, path)
if result is False:
return False
# create the versioninfo.json file for the shot container
details = entity.copy()
details["product"] = usdApi.getShotUsdName()
hVersion = self.core.products.getVersionFromFilepath(path)
details["version"] = hVersion
details["comment"] = comment
infoPath = self.core.products.getVersionInfoPathFromProductFilepath(
path
)
self.core.saveVersionInfo(
filepath=infoPath,
details=details
)
# update the master version of the shot container
useMaster = self.core.products.getUseMaster()
if useMaster:
self.core.products.updateMasterVersion(path)
# define which departmentlayers will be created
deps = ["Layout", "Animation", "Lighting", "Custom"]
for dep in deps:
# create department layers
usdApi.createDepartmentLayerForEntity(entity, dep)
deplayerPath = usdApi.getLatestDepartmentLayerPath(entity, dep, includeMaster=False)
stage = self.getStageForDepartment(dep)
framerange = self.core.entities.getShotRange(entity)
if framerange:
start = framerange[0]
end = framerange[1]
else:
start = end = None
usdApi.setFrameRangeInStage(stage, start, end)
usdApi.saveStage(stage, deplayerPath)
# create sublayers for department layers
if dep == "Layout":
sublayer = "camera"
usdApi.createSublayerLayerForDepartment(entity, dep, sublayer)
sublayerPath = usdApi.getLatestSublayerPath(entity, dep, sublayer, includeMaster=False)
stage = self.getCameraStage()
usdApi.setFrameRangeInStage(stage, start, end)
usdApi.saveStage(stage, sublayerPath)
elif dep == "Custom":
sublayer = "customSublayer1"
usdApi.createSublayerLayerForDepartment(entity, dep, sublayer)
sublayerPath = usdApi.getLatestSublayerPath(entity, dep, sublayer, includeMaster=False)
stage = self.getCustom1Stage()
usdApi.setFrameRangeInStage(stage, start, end)
usdApi.saveStage(stage, sublayerPath)
sublayer = "customSublayer2"
usdApi.createSublayerLayerForDepartment(entity, dep, sublayer)
sublayerPath = usdApi.getLatestSublayerPath(entity, dep, sublayer, includeMaster=False)
stage = self.getCustom2Stage()
usdApi.setFrameRangeInStage(stage, start, end)
usdApi.saveStage(stage, sublayerPath)
def getStageForDepartment(self, department):
# create a default stage with prims in memory for a specific department
stage = Usd.Stage.CreateInMemory()
if department == "Layout":
stage.DefinePrim("/assets", "Scope")
elif department == "Lighting":
stage.DefinePrim("/lights", "Xform")
return stage
def getCameraStage(self):
# create the stage for the camera sublayer of the Layout departmentlayer
stage = Usd.Stage.CreateInMemory()
stage.DefinePrim("/cameras/shotcam", "Camera")
return stage
def getCustom1Stage(self):
# create a custom stage for the sublayer of the Custom departmentlayer
stage = Usd.Stage.CreateInMemory()
stage.DefinePrim("/custom1", "Scope")
return stage
def getCustom2Stage(self):
# create another custom stage for another sublayer of the Custom departmentlayer
stage = Usd.Stage.CreateInMemory()
stage.DefinePrim("/custom2", "Scope")
return stage