From 160f07c5bd771c36099d8a1551486c7bf865870f Mon Sep 17 00:00:00 2001 From: Pierre Baillargeon Date: Wed, 4 Dec 2024 12:09:45 -0500 Subject: [PATCH] EMSUSD-1891 Don't dirty stage when loading - Don't create light attributes when reading them. - Make all set function create the attribute if it does not exists. - Add a unit test for loading stage with lights not being dirty. --- lib/mayaUsd/ufe/UsdLight.cpp | 86 +++++++++++++++---------- test/lib/ufe/testLight.py | 38 +++++++++-- test/testSamples/light/SimpleLight.usda | 5 ++ 3 files changed, 90 insertions(+), 39 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdLight.cpp b/lib/mayaUsd/ufe/UsdLight.cpp index a6eab751f3..2a56f4e215 100644 --- a/lib/mayaUsd/ufe/UsdLight.cpp +++ b/lib/mayaUsd/ufe/UsdLight.cpp @@ -143,7 +143,10 @@ void setLightIntensity(const UsdPrim& prim, float attrVal) const UsdLuxLightAPI lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetIntensityAttr(); - lightAttribute.Set(attrVal); + if (!lightAttribute) + lightSchema.CreateIntensityAttr(VtValue(attrVal)); + else + lightAttribute.Set(attrVal); } Ufe::Light::IntensityUndoableCommand::Ptr UsdLight::intensityCmd(float li) @@ -172,8 +175,10 @@ void setLightColor(const UsdPrim& prim, const Ufe::Color3f& attrVal) { const UsdLuxLightAPI lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetColorAttr(); - - lightAttribute.Set(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b())); + if (!lightAttribute) + lightSchema.CreateColorAttr(VtValue(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b()))); + else + lightAttribute.Set(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b())); } Ufe::Light::ColorUndoableCommand::Ptr UsdLight::colorCmd(float r, float g, float b) @@ -194,12 +199,6 @@ bool getLightShadowEnable(const UsdPrim& prim) const UsdLuxShadowAPI shadowAPI(prim); PXR_NS::UsdAttribute lightAttribute = shadowAPI.GetShadowEnableAttr(); - if (!lightAttribute) { - // If the shadow enable attribute is not created yet, create one here - lightAttribute = shadowAPI.CreateShadowEnableAttr(VtValue(true)); - return true; - } - bool val = false; lightAttribute.Get(&val); return val; @@ -210,9 +209,10 @@ void setLightShadowEnable(const UsdPrim& prim, bool attrVal) const UsdLuxShadowAPI shadowAPI(prim); const PXR_NS::UsdAttribute lightAttribute = shadowAPI.GetShadowEnableAttr(); - if (lightAttribute) { + if (lightAttribute) lightAttribute.Set(attrVal); - } + else + shadowAPI.CreateShadowEnableAttr(VtValue(attrVal)); } Ufe::Light::ShadowEnableUndoableCommand::Ptr UsdLight::shadowEnableCmd(bool se) @@ -232,11 +232,6 @@ Ufe::Color3f getLightShadowColor(const UsdPrim& prim) const UsdLuxShadowAPI shadowAPI(prim); PXR_NS::UsdAttribute lightAttribute = shadowAPI.GetShadowColorAttr(); - if (!lightAttribute) { - // If the shadow color attribute is not created yet, create one here - lightAttribute = shadowAPI.CreateShadowColorAttr(); - } - GfVec3f val(0.f, 0.f, 0.f); lightAttribute.Get(&val); return Ufe::Color3f(val[0], val[1], val[2]); @@ -246,8 +241,10 @@ void setLightShadowColor(const UsdPrim& prim, const Ufe::Color3f& attrVal) { const UsdLuxShadowAPI shadowAPI(prim); const PXR_NS::UsdAttribute lightAttribute = shadowAPI.GetShadowColorAttr(); - - lightAttribute.Set(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b())); + if (!lightAttribute) + shadowAPI.CreateShadowColorAttr(VtValue(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b()))); + else + lightAttribute.Set(GfVec3f(attrVal.r(), attrVal.g(), attrVal.b())); } Ufe::Light::ShadowColorUndoableCommand::Ptr UsdLight::shadowColorCmd(float r, float g, float b) @@ -280,8 +277,10 @@ void setLightDiffuse(const UsdPrim& prim, float attrVal) { const UsdLuxLightAPI lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetDiffuseAttr(); - - lightAttribute.Set(attrVal); + if (!lightAttribute) + lightSchema.CreateDiffuseAttr(VtValue(attrVal)); + else + lightAttribute.Set(attrVal); } Ufe::Light::DiffuseUndoableCommand::Ptr UsdLight::diffuseCmd(float ld) @@ -310,8 +309,10 @@ void setLightSpecular(const UsdPrim& prim, float attrVal) { const UsdLuxLightAPI lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetSpecularAttr(); - - lightAttribute.Set(attrVal); + if (!lightAttribute) + lightSchema.CreateSpecularAttr(VtValue(attrVal)); + else + lightAttribute.Set(attrVal); } Ufe::Light::SpecularUndoableCommand::Ptr UsdLight::specularCmd(float ls) @@ -340,8 +341,10 @@ void setLightAngle(const UsdPrim& prim, float attrVal) { const UsdLuxDistantLight lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetAngleAttr(); - - lightAttribute.Set(attrVal); + if (!lightAttribute) + lightSchema.CreateAngleAttr(VtValue(attrVal)); + else + lightAttribute.Set(attrVal); } Ufe::Light::AngleUndoableCommand::Ptr UsdDirectionalInterface::angleCmd(float la) @@ -371,8 +374,10 @@ void setLightSphereProps(const UsdPrim& prim, const Ufe::Light::SphereProps& att { const UsdLuxSphereLight lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetRadiusAttr(); - - lightAttribute.Set(attrVal.radius); + if (!lightAttribute) + lightSchema.CreateRadiusAttr(VtValue(attrVal.radius)); + else + lightAttribute.Set(attrVal.radius); } Ufe::Light::SpherePropsUndoableCommand::Ptr @@ -416,12 +421,22 @@ void setLightConeProps(const UsdPrim& prim, const Ufe::Light::ConeProps& attrVal { const UsdLuxShapingAPI lightSchema(prim); const PXR_NS::UsdAttribute focusAttribute = lightSchema.GetShapingFocusAttr(); + if (!focusAttribute) + lightSchema.CreateShapingFocusAttr(VtValue(attrVal.focus)); + else + focusAttribute.Set(attrVal.focus); + const PXR_NS::UsdAttribute coneAngleAttribute = lightSchema.GetShapingConeAngleAttr(); - const PXR_NS::UsdAttribute coneSoftnessAttribute = lightSchema.GetShapingConeSoftnessAttr(); + if (!coneAngleAttribute) + lightSchema.CreateShapingConeAngleAttr(VtValue(attrVal.angle)); + else + coneAngleAttribute.Set(attrVal.angle); - focusAttribute.Set(attrVal.focus); - coneAngleAttribute.Set(attrVal.angle); - coneSoftnessAttribute.Set(attrVal.softness); + const PXR_NS::UsdAttribute coneSoftnessAttribute = lightSchema.GetShapingConeSoftnessAttr(); + if (!coneSoftnessAttribute) + lightSchema.CreateShapingConeSoftnessAttr(VtValue(attrVal.softness)); + else + coneSoftnessAttribute.Set(attrVal.softness); } Ufe::Light::ConePropsUndoableCommand::Ptr @@ -459,7 +474,10 @@ void setLightNormalize(const UsdPrim& prim, bool attrVal) const UsdLuxRectLight rectLight(prim); const PXR_NS::UsdAttribute lightAttribute = rectLight.GetNormalizeAttr(); - lightAttribute.Set(attrVal); + if (!lightAttribute) + rectLight.CreateNormalizeAttr(VtValue(attrVal)); + else + lightAttribute.Set(attrVal); } Ufe::Light::NormalizeUndoableCommand::Ptr UsdAreaInterface::normalizeCmd(bool nl) @@ -505,8 +523,10 @@ void setLightVolumeProps(const UsdPrim& prim, const UFE_LIGHT_BASE::VolumeProps& { const UsdLuxSphereLight lightSchema(prim); const PXR_NS::UsdAttribute lightAttribute = lightSchema.GetRadiusAttr(); - - lightAttribute.Set(attrVal.radius); + if (!lightAttribute) + lightSchema.CreateRadiusAttr(VtValue(attrVal.radius)); + else + lightAttribute.Set(attrVal.radius); } void UsdCylinderInterface::volumeProps(float radius, float length) diff --git a/test/lib/ufe/testLight.py b/test/lib/ufe/testLight.py index bb0800d2a3..e436076f91 100644 --- a/test/lib/ufe/testLight.py +++ b/test/lib/ufe/testLight.py @@ -22,7 +22,7 @@ import ufeUtils import usdUtils -from pxr import Gf +from pxr import Gf, Sdf from maya import cmds from maya import standalone @@ -75,9 +75,10 @@ def _StartTest(self, testName): cmds.file(force=True, new=True) self._testName = testName testFile = testUtils.getTestScene("light", self._testName + ".usda") - mayaUtils.createProxyFromFile(testFile) + shapeNode, shapeStage = mayaUtils.createProxyFromFile(testFile) globalSelection = ufe.GlobalSelection.get() globalSelection.clear() + return shapeNode, shapeStage def _TestSpotLight(self, ufeLight, usdLight): # Trust that the USD API works correctly, validate that UFE gives us @@ -240,8 +241,9 @@ def _TestAreaProps(self, ufeLight, usdLight): self.assertEqual(usdAttr.Get(), ufeLight.areaInterface().normalize()) def testUsdLight(self): - self._StartTest('SimpleLight') - mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape') + shapeNode, _ = self._StartTest('SimpleLight') + + mayaPathSegment = mayaUtils.createUfePathSegment(shapeNode) # test spot light spotlightUsdPathSegment = usdUtils.createUfePathSegment('/lights/spotLight') @@ -281,8 +283,8 @@ def testUsdLight(self): @unittest.skipUnless(os.getenv('UFE_VOLUME_LIGHTS_SUPPORT', 'FALSE') == 'TRUE', 'UFE has volume light support.') def testUsdVolumeLights(self): - self._StartTest('SimpleLight') - mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape') + shapeNode, _ = self._StartTest('SimpleLight') + mayaPathSegment = mayaUtils.createUfePathSegment(shapeNode) # test cylinder light cylinderlightUsdPathSegment = usdUtils.createUfePathSegment('/lights/cylinderLight') cylinderlightPath = ufe.Path([mayaPathSegment, cylinderlightUsdPathSegment]) @@ -319,6 +321,30 @@ def testUsdVolumeLights(self): usdDomeLight = usdUtils.getPrimFromSceneItem(domelightItem) self._TestDomeLight(ufeDomeLight, usdDomeLight) + def testLoadingLight(self): + ''' + Verify that the act of loading a stage with lights does not dirty the stage. + ''' + shapeNode, stage = self._StartTest('SimpleLight') + mayaPathSegment = mayaUtils.createUfePathSegment(shapeNode) + + # Verify the stage is not dirty + def verifyClean(): + layer: Sdf.Layer = stage.GetRootLayer() + self.assertFalse(layer.dirty) + + verifyClean() + + # Access the cylinder light shadow enable attribute. + noAttrlightUsdPathSegment = usdUtils.createUfePathSegment('/lights/noAttrLight') + noAttrlightPath = ufe.Path([mayaPathSegment, noAttrlightUsdPathSegment]) + noAttrlightItem = ufe.Hierarchy.createItem(noAttrlightPath) + + ufeLight = ufe.Light.light(noAttrlightItem) + self.assertFalse(ufeLight.shadowEnable()) + + verifyClean() + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/test/testSamples/light/SimpleLight.usda b/test/testSamples/light/SimpleLight.usda index 7ba33fc91c..e4f4a2c15d 100644 --- a/test/testSamples/light/SimpleLight.usda +++ b/test/testSamples/light/SimpleLight.usda @@ -70,5 +70,10 @@ def Xform "lights" color3f inputs:shadow:color bool inputs:shadow:enable = 1 } + + def CylinderLight "noAttrLight" + { + } + }